home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d12
/
wasm201.arc
/
WASM.DOC
< prev
Wrap
Text File
|
1988-07-17
|
196KB
|
4,738 lines
\\\ WASM ///
Wolfware Assembler
Version 2.01
User's Manual
(C) Copyright 1987 by Eric Tauck
Wolfware Programs
Table of Contents
Introduction ....................................... 1
Distribution Policy ................................ 3
Assembling Programs ................................ 4
Basic Syntax ....................................... 6
Symbols .......................................... 8
Instructions ..................................... 9
Operands ........................................ 10
Operand Expressions ............................. 14
Program Structure ................................. 16
Procedures ........................................ 17
Conditional Assembly .............................. 18
Conditional Directives .......................... 19
Nested Conditional Assembly ..................... 22
Conditional Operators ........................... 24
Conditional Operand Testing ..................... 25
Macros ............................................ 27
Defining Macros ................................. 28
Invoking Macros ................................. 30
Nested Macros ................................... 32
Conditional Macros .............................. 33
Listing of Macros ............................... 34
Data .............................................. 35
Assembly Directives ............................... 37
Functional Operands ............................... 55
Assembly Constants ................................ 61
Reserved Symbols .................................. 64
Assembly Listing .................................. 65
Symbol Table Listing .............................. 67
Assembly Messages ................................. 68
Instruction Set ................................... 79
External Subroutines .............................. 91
Source Code Clarification ......................... 92
Memory Limitations ................................ 96
Bibliography ...................................... 97
Index ............................................. 98
Introduction 1
Introduction
Wolfware Assembler (WASM) is an assembly language compiler for the
IBM PC and compatibles. It takes a standard ASCII text file of
8086 instruction mnemonics for input and produces an executable
COM file and an optional list file for output.
- Minimum system requirements: 8086 based or machine language
compatible computer, MS/PC DOS 2.00 or up, and about 100
kilobytes of free memory.
- Features: supports full range of 8086 instructions and
addressing, most standard assembly directives, signed and
unsigned numbers, operand expressions, conditional assembly,
macros, produces executable code (does not require linking), and
fairly fast operation.
Assembly language is a programming language in which the source
statements are translated directly into individual microprocessor
instructions. This direct translation allows complete control
over the computer and the greatest possible optimization of a
program. Programming in assembly language has immediate and
practical benefits:
- Programs can be made to run hundreds, maybe thousands of times
faster than their high level language counterparts.
- Programs are usually much smaller and more efficient.
- Programs can take full advantage of the system it is meant to
run on.
Assembly language is essential where speed, compactness, and low
level or hardware control are the primary requirements. WASM is
best suited for writing smaller, stand-alone programs and
optimized routines that are used by other programs. WASM is ideal
for writing machine language subroutines for BASIC or Turbo
Pascal.
The disadvantage of assembly language is that the writing and
debugging of such programs are often more difficult. Another
consideration is that assembly language is not very portable, i.e.
programs written in assembly language are usually restricted to
one type of computer.
WASM is easier to use than most commercial assemblers because of
its simplified syntax and program structure. Of course, by the
same token, WASM is not necessarily compatible with other
assemblers.
2 Introduction
Though this documentation explains some of the basic concepts of
assembly language, no attempt is made to to teach it. The user
should be familiar with the basic concepts of programming and have
a general knowledge of the the 8086 microprocessor. See the
bibliography for some possible reference materials.
Distribution Policy 3
Distribution Policy
You are encouraged to freely share and distribute unmodified
copies of this program and documentation. A nominal fee may be
charged to cover the costs of duplication and distribution.
If you find this program useful, you are expected to help support
its development by registering your copy. To register, send $10
to:
Eric Tauck
Wolfware Programs
1304 Deerpass Road
Marengo, IL 60152
You can use the registration form in the file REGFORM.DOC for this
purpose. Please make checks payable to Eric Tauck.
Registration entitles you to one year of support, which includes:
1) Notification of any significant new versions of WASM.
2) The option to upgrade at any time for $5.
The terms and prices of registration will be effective at least
through 1987. Whether you register or not, feel free to comment
about the program or documentation. In addition to the address
above, I can also be reached electronically at:
BIX ........... etauck
CompuServe .... 72457,1557
GEnie ......... e.tauck
People/Link ... ofr215
I usually check for electronic mail twice a week.
4 Assembling Programs
Assembling Programs
Programs are assembled by running the assembler and specifying the
names of the source, object, and list files. To run the assembler
from any DOS prompt, you type "WASM" and then a carriage return.
A brief opening message will be displayed and you will be prompted
for all the required information. Default file names will be
provided if no name is otherwise specified. The default name
appears in brackets at the end of the prompt line. An entire file
name consists of a path, filename, and extension. The drive
specification is considered part of the path.
The source file contains the list of instructions that are to be
assembled into machine code. It must be a standard ASCII text
file created by the user before assembly. If you enter a source
file name without an extension, the default extension of ASM will
be automatically added to it. ASM is the standard filename
extension for assembler source files.
The object file contains the machine code result of the assembly.
The object file will be created if it doesn't already exist; if
does exist the original file will be overwritten. The default
name is the source path and filename with an extension COM. You
may enter any component(s) of the name which you want to be
different from the default name (like only the path and extension
for instance). COM is reserved by DOS as the filename extension
for executable "command" files. The object file is not a linkable
object file, but a binary image of the compilation. The object
file, assuming the source code was logically correct and that
there were no errors during assembly, is directly executable from
DOS. If you use the extension COM, you can run the assembled
program just by typing its filename.
The list file contains the listing of the assembly. The list file
will be created if it doesn't already exist; if does exist the
original file will be overwritten. If no list file is specified,
no listing will be produced. If you do enter a filename, the
object path and an extension of LST will be used as the default.
Specifying CON as the list file will send the listing to the
screen, and specifying PRN as the list file will send the listing
to the printer. The listing itself is more thoroughly described
under Assembly Listing.
The names of the three files may be entered on the command line
when WASM is initially executed. To do this you must provide at
least the name of the source file. The other two names are
optional. All names should be separated from each other by a
comma. You can use a default name by placing a comma without a
name, or by just leaving the name off the end. The normal
defaults to all names still apply. WASM will display the names of
the three files taken from the command line.
Assembling Programs 5
Examples of command line file specifications:
WASM TEST
source is TEST.ASM, object is TEST.COM, and there is no list
WASM ABC, , ABC
source is ABC.ASM, object is ABC.COM, and list is ABC.LST
WASM SUBRT, .BLD
source is SUBRT.ASM, object is SUBRT.BLD, and there is no list
WASM TEST.TXT, STUPID.BIN, HELLO.DOC
source is TEST.TXT, object is STUPID.BIN, and list is
HELLO.DOC
WASM A:\ASSM\PROG1,,B:PROG1
source is A:\ASSM\PROG1.ASM, object is A:\ASSM\PROG1.COM, and
the list is B:PROG1.LST
WASM GAME.SRC, C:\GAMES\.COD, C:\LISTS\GAME
source is GAME.SRC, object is C:\GAMES\GAME.COD, and the list
is C:\LISTS\GAME.LST
If there are errors detected during assembly, they will be
displayed in the listing. If there is no listing being generated,
the errors will be displayed to the screen along with the line
causing the error. Any errors should be corrected and the program
reassembled before running or debugging the program.
At the end of assembly several statistics are displayed: the
number of errors, the number of lines assembled, the number of
bytes of code, and the number of symbols defined. These
statistics are sent to the list file if a listing is being
generated, otherwise they will be displayed to the screen. A
message stating if any errors where detected will shown if the
assembly statistics were not displayed to the screen.
An error code is returned upon termination. This error code can
be acted upon in a batch file with ERRORLEVEL (see your DOS manual
for details). The error codes are as follows:
Code Meaning
---- -------
0 no lines flagged
1 lines were flagged for comment but no errors were detected
2 errors were detected but the assembly was completed
3 the assembly was prematurely terminated due to errors
4 assembly could not begin (incorrect DOS or not enough mem.)
6 Basic Syntax
Basic Syntax
The source file must be a standard ASCII text file. The only
control characters given special treatment are line boundaries
(ASCII codes 13 and 10) and end of file markers (ASCII code 26).
All other control characters are treated as spaces. The source
lines may be up to 160 characters long. If the source file does
not have an end of file marker, the assembler will read the number
of bytes recorded in the directory. The line editor EDLIN.COM
provided with DOS is suitable for creating source files.
All 8086 instructions perform an operation on zero, one, or two
operands. Assembly directives (commands to control the assembler
itself) are implemented in a similar manner. Generally each line
will contain a single 8086 instruction, or directive, and its
operands. In addition to instructions and their operands, a line
may contain a symbol declaration.
The source file is assembled line by line. Each line is divided
up into fields separated by delimiters. Delimiters consist of
spaces and most control characters. How the assembler tries to
interpret each field is based on the location of the field within
the line. Lines are interpreted according to the following
format:
Symbol Instruction Operands ;Comment
Symbols must begin on the first character of the line. If the
first character of a line is a delimiter, the line is assumed not
to contain a symbol declaration. Symbols are only required when
the instruction is one that specifically defines some sort of
symbol (like an equate or macro declaration). Symbols may be any
length as long as they fit on the line. Symbols may consist of
most characters as long as they are unique from each other and all
predefined symbols. The rule of thumb is to start symbols with a
letter and make the rest of the symbol out of numbers, letters,
and underscores. Restrictions on symbol declarations are more
thoroughly described under Reserved Symbols. Symbols in general
are described under Symbols.
Instructions must be separated by at least one delimiter from the
symbol. If there is no symbol, at least one delimiter must
precede the instruction (so it doesn't start on the first
character of the line). All instructions are predefined. See
Instructions.
Operands must be separated by at least one delimiter from the
instruction. Since a single operand may consist of multiple
fields, operands must be separated from each other by commas. The
instruction determines how many of what kind of operands are
required. See Operands.
Basic Syntax 7
Comments come at the end of the line after a semi-colon. Comments
may consist of anything and be any length as long as they fit on
the line. Comments are always optional and are only there to
assist the programmer in understanding the source code.
Blank lines may be placed in the source code to improve
readability. Blank lines are ignored by the assembler. Lines may
also contain only a comment, in which case they are treated as
blank lines.
8 Symbols
Symbols
Symbols are used to identify certain aspects of the source
program. Symbols allow those aspects to be referenced
symbolically. The effective use of symbols can make a program
easier to understand. Symbols can also simplify the modification
of a program. By changing the portion of the program represented
by the symbol, you automatically change the program at every
location the symbol is used.
A symbol is created by declaring it. This is done by placing the
symbol field on the first column of a source line. A line may
contain only a symbol, or only a symbol and a comment. Declaring
a symbol causes the assembler to internally store it in the symbol
table. An ambiguity arises if a particular field is defined more
than once as a symbol, since if that symbol is used, the assembler
will not be able to tell which definition is actually being
accessed. For this reason, all symbols must be unique from each
other. In addition to being unique from each other, programmer
defined symbols must be unique from all predefined symbols.
Restrictions on symbol declarations are more thoroughly described
under Reserved Symbols.
Symbols come in several different types, the most common of which
is the label. Labels identify a location in memory. Labels are
used for two purposes, branching and data access. Labels for
branching are called near labels. Labels for data access are
called memory labels. Memory labels come in different sizes
according to how many bits of memory are referenced. The other
symbol types are equates and macros. Equates represent a single
number. Macros represent an entire series of instructions.
The symbol type is determined by the instruction. The declaration
directives (DB, DW, and DS) create memory labels, the EQU
directive creates an equate, the MACRO directive creates a macro,
and the LABEL directive creates a label of a specified type. Most
other instructions, and symbols on lines without instructions,
result in near labels.
Symbols are used by the program in two different ways, as
instructions and as operands. Only macros are used as
instructions. The remaining symbol types are used as operands. A
symbol does not have to be declared before it is used, i.e. memory
references, equates, and macros may be declared anywhere in the
program. Near labels should be placed at the location where the
code execution should continue after the branch.
Instructions 9
Instructions
An 8086 instruction specifies the action that should be carried
out on the operands by the microprocessor. Assembly directives
are special instructions to control the assembly itself. 8086
instructions and directives are implemented in the same manner,
there is no syntactic difference between the two.
Over a hundred different instructions are recognized by the 8086
microprocessor. The two major types of instructions are those
that manipulate bits in memory and those that transfer control
from one location in the program to another. A summary of all the
legal instructions can be found under Instruction Set. For a full
explanation of all 8086 instructions, you should acquire a book on
the subject.
There are assembly directives for many different purposes.
Specific assembly directives are described in their relevant
sections and under Assembly Directives.
10 Operands
Operands
The operands describe what is being acted upon by the instruction.
There are many different types of operands. The number and type
of operands required is determined by the particular instruction.
The operands needed for an instruction can be looked up under
Instruction Set. WASM figures out the type of an operand by
looking at it and trying to match it to one of the formats it
recognizes. If the operand is not recognized as a standard
predefined type, the symbol table is searched to see if has been
defined by the programmer.
The following is a list of the legal operand types and their
formats:
I. Immediate data operands.
A. Numbers with an optional plus or minus preceding it. All
numbers must begin with a 0 to 9, and anything that begins
as such is considered a number. Numbers with a sign must
be in the range -32768 to +32767, otherwise they must be 0
to 65535
1. A binary number of up to 16 digits of ones and zeros
followed by a "B".
2. A decimal number from 0 to 65535.
3. A hexadecimal number of up to 4 digits of 0 to F
followed by an "H". Hexadecimal numbers that begin
with A to F should have a preceding 0.
B. A character enclosed in single quotes. The character is
converted to an 8 bit ASCII value, so 'z' would be the
same as the number 122.
C. A pair of characters enclosed in single quotes. The
characters are converted to a 16 bit value calculated from
their ASCII values. If 'ab' where moved into a register,
the high byte would receive the value of 'b' and the low
byte would receive the value of 'a'. 'ab' is the same as
the number (98*256)+97 = 25185 or 6261H. The values of
'a' and 'b' are backwards because of the way the 8086
stores 16 bit numbers.
D. Assembly constants. These are special symbols that return
a value set by the assembler. See Assembly Constants.
II. Register operands.
A. One of the following 8 bit registers:
AH AL BH BL CH CL DH DL
Operands 11
B. One of the following 16 bit registers:
AX BX CX DX SP BP SI DI
C. One of the following segment registers:
CS SS DS ES
III. Memory operands.
A. Direct addressing with a value enclosed by brackets. All
numbers (immediate data) inside the brackets are added or
subtracted together to form the value.
B. Indirect addressing through the use of one of the
following register combinations with an optional value
added or subtracted in:
BX BP DI SI
BX+DI BX+SI BP+DI BP+SI
All the addressing components should be surrounded by
brackets. The registers can appear in any order and may
be mixed up with any numbers. All numbers (immediate
data) are added or subtracted together to form the value.
The OFFSET function is assumed for any labels (OFFSET can
be left out).
IV. A string of any sequence of characters surrounded by single
quotes. Note: single quotes cannot be represented as a
character in a string or as an immediate data character, it
can only be represented as a numerical value.
V. A single question mark. This means the the programmer
doesn't know or care what the operand is. A question mark is
interpreted as a zero.
VI. Certain symbols types are used as operands, including equates
and labels. See Symbols.
VII. Functional operands may be used to modify or isolate specific
aspects of of other operands. See Functional Operands.
Operands always have a size associated with them (measured in
bits). If the instruction is one that transfers data from one
operand to another, the sizes of the operands for the instruction
must agree.
The size of immediate data is the number bits it represents.
Usually 8 bits of immediate data is compatible with 16 bits (i.e
WASM is smart enough to extend 8 bits of data into 16 bits).
12 Operands
Immediate data sizes:
Immediate Data Size in Bits
-------------- ------------
unsigned number 0 to 255 8 or 16
signed number -128 to 127 8 or 16
character in quotes 8 or 16
unsigned number 0 to 65535 16
signed number -32728 to 32727 16
double character in quotes 16
The size of register and memory operands are the number of bits
that can be moved in and out of them. The size of registers are
predefined. The size of memory operands must be defined in the
declaration or with a functional operand that sets the size. If a
memory operand is being operating upon with a register, the memory
operand is assumed to be the same size as the register.
Examples of operands:
;*** Immediate Data ***
Mov Dh, -100
Mov Bl, 00101001b
Mov Al,'W' ;move the ASCII value of upper-case w to AL
Mov Ax,', ' ;move a comma and space into AX,
Stosw ;it is stored in the same order (comma first)
;remember that numbers MUST start with 0 to 9, even
;hexadecimal numbers
Mov Ax,0ffffh ;move ffff hex to AX
;*** Registers ***
;8 bit examples
Mov AL,DL
Mov CL,0
;16 bit examples
Mov Ax,Dx
Mov Cx,0
;segment examples
Mov Dx,Ss
Mov Cx,0 ;
Mov Es,Cx ;cannot move immed. directly to seg
Operands 13
;*** Memory operands ***
;direct reference examples
Mov [100],Ax ;size is the same as AX
Mov Byte [100], 0 ;size is set with BYTE
Push Data ;DATA is defined below, not ambiguous
Mov Data,0
;the next three produce the same effect
Mov CX,[Data] ;OFFSET implied
Mov CX,[Offset Data]
Mov CX,Data ;this is best
;indirect reference examples
Mov [Bx],Ax
Mov Dx,[Bx+Si+100]
Inc Byte [Offset Data+Di-1001011b+Bp-3]
Mov Cx, [Data+Bx] ;BX acts as an index into DATA
Data Dw ?
;*** Near labels ***
Label1 ;no code, points to line below
Lable2 Label Near ;a label declaration, same as above
Label3 Nop ;points to its own instruction
;
;all three of these jump to the NOP instruction above
Jmps Label1
Jmps Label2
Jmps Label3
;*** Strings ***
Db 'this is a string'
Db 'it',39,'s cold' ;this declares the string "it's cold"
14 Operand Expressions
Operand Expression
Immediate data operands may be combined into expressions. Any
number of operands may be combined sequentially. Parenthesis may
also be used within expressions to control the order of
evaluation. Parenthesis can be nested approximately ten deep. A
sign may come before parenthesis, but the range of the value
within the parenthesis is not checked. All operand expressions
are evaluated during assembly.
Near and memory labels may also be modified via expressions. Any
immediate data operands may be combined with a near or memory
label. Adding or subtracting a value to or from a label has the
effect of an additional displacement. The label must be the first
component of the expression.
The legal operators for combining operands are:
Operator Function
-------- --------
+ addition <--) Arithmetic
- subtraction )
* multiplication )
/ division )
\ remainder )
MOD remainder <--)
AND and <----) Logic
OR or )
XOR xor <----)
= equals <------) Conditional
< less than )
> greater than <------)
The use of conditional operators are described under Conditional
Operators, the other operators carry out the specified standard
arithmetic and logic operations. If some sort of error occurs
with AND, OR, XOR, or MOD, instead of displaying the literal
operator, only the first letter A, O, X, or \ for MOD will be
displayed.
Examples of operand expressions:
;the following lines all assemble to "move zero to AX"
Mov Ax,0
Mov Ax,-21 + ((20 Mod 19)+ 20)
Mov Ax,-21 - -21
Mov Ax,50000 * (10\10)
Mov Ax,-6 / -3 - 2
Mov Ax,Not (1111111111111110b Or (0feh Xor (65535 And 1)))
Mov Ax,0ffh-128-64-32-16-8-4-2-1
Operand Expressions 15
;here is how to load a double word
;of storage a word at a time
Mov Word Location, Offset Routine ;load first word
Mov Ax, Ds
Mov Word Location + 2, Ax ;load second word
Location Label Dword
Ds 4
16 Program Structure
Program Structure
Though programs may be organized in any fashion, it is usually a
good idea to make them "structured." Structured programs are
generally easier to understand and modify. Because of their
inherently straightforward design, structured programs are less
likely to contain errors and usually accomplish the task with a
minimum of code.
Structured programming divides a program into separate routines,
each of which is treated like a separate program. Every routine
encompasses a single or group of functions that make up the total
operation of the program. Direct transfer of control from one
routine to another is not allowed. Direct communication between
routines is also not allowed. A routine may call another routine,
but when the other routine is finished, control must be returned
to the caller. Information should only be passed from a routine
to its subroutine by parameters or by data that is explicitly
intended as global.
Assembly language doesn't naturally lend itself to structured
programming the way a high-level language like Pascal does. There
is nothing to prevent the programmer from entering a routine and
then jumping directly to another routine. WASM provides two
methods to assist in creating a structured program: procedures and
macros. The implementation for procedures and macros are
described under Procedures and Macros, respectively.
Procedures 17
Procedures
A procedure is a type of programmer defined routine. A procedure
is accessed with the 8086 CALL instruction. Only one copy of a
procedure exists, unlike macros, which, in the process of
assembly, create a copy of their routine every time they are
invoked. The use of procedures makes a program shorter but
slower. Lengthy routines should always be declared as procedures,
especially if they are called in many different places.
Parameters are passed to procedures through registers or by
placing the data on the stack.
Procedures are implemented by the PROC and ENDP directives. PROC
starts a procedure. Its operand is either NEAR, for routines in
the same segment, or FAR, for routines that may be in another
segment. All procedures that are called from within the program
should be NEAR. FAR should be used by procedures that will be
called externally from another program, like a machine language
BASIC subroutine, or for routines that are called indirectly, like
an interrupt handler. A symbol may be declared along with the
PROC directive. This symbol becomes the label that identifies the
procedure and is used when calling it. ENDP finishes a procedure.
It has no operands.
The last executed 8086 instruction in a procedure should be a RET.
This instruction will return control to the code that called the
routine in the first place.
Procedures may be nested up to ten deep. The nest number of a
procedure is displayed in the listing, see Assembly Listing.
Nesting a procedure doesn't really make it local, as is implied,
though it still should be treated as if it were. Procedures
should not be called outside of the procedure that they were
declared in. Also data declared inside of a procedure should not
be accessed outside of it.
Procedural declarations create object code. This means that the
program must either jump around them or the declarations must be
placed somewhere out of the way, like at the end of the program.
;small example of program structure and
;syntax using procedures
Main Proc Far ;start of main program
: ;main program
Call Subrt ;transfer control to the subroutine
: ;main program
Subrt Proc Near ;start of subroutine declaration
: ;subroutine code
Ret ;returns control to main program
Endp ;end of subroutine declaration
Endp ;end of main program
18 Conditional Assembly
Conditional Assembly
Conditional assembly is to assemble or skip certain defined parts
of the source code based on programmer defined conditions.
Conditional assembly may be used anywhere within a program, to
enable or disable any sections of source code. Source code that
is disabled (skipped) has no effect upon the assembly.
Conditional assembly is probably most useful in macros, where the
programmer may want a macro to assemble in a certain way based
upon its parameters.
Conditional assembly is controlled by special conditional
directives. These directives themselves never show up in the
listing.
Conditional Directives 19
Conditional Directives
Conditional assembly is controlled by the IF, IFN, NEXTIF, ELSEIF,
ELSE, and ENDIF directives. All conditional sections of code must
start with an IF or IFN and end with an ENDIF. The other
directives, NEXTIF, ELSEIF, and ELSE, may optionally be used in
the middle.
The IF directive starts a conditional section of code. The IF
directive can be thought of as "if the condition is true, then
assemble the following code." The "condition" for conditional
directives is a single immediate data operand. The operand is
true if its value is not equal to zero, false if its value is
equal to zero. If the condition is false, all the source code
after the IF is skipped up until a matching ENDIF or another
conditional statement is reached.
;IF is true, MOV AX,1 is assembled
If 9283 ;value not equal to zero, true
Mov Ax,1
Endif
;IF is false, ADD DX,CX is not assembled
If 0 ;value equal to zero, false
Add Dx,Cx
Endif
The IFN directive works just like an IF directive except that the
condition is reversed. IFN can be thought of as "if the condition
is not true then assemble the following code." IFN starts a
section of conditional code, just like IF.
;the IFN condition is false, so the
;MOV AX,1 is assembled
Ifn 0 ;value is zero, false
Mov Ax,1
Endif
;the IFN condition is true, ADD DX,CX
;is not assembled
Ifn -6 ;value not equal to zero, true
Add Dx,Cx
Endif
The NEXTIF directive works like an ENDIF/IF combination. If a
NEXTIF is encountered, the present present conditional block of
code is finished (like an ENDIF) and a new conditional block is
started (like an IF). NEXTIF, like IF, has a single conditional
operand. Any number of NEXTIF's may follow an IF. NEXTIF's are
most useful for defining a sequential series of source code blocks
in situations where none, some, or all of the blocks may be
assembled or skipped.
20 Conditional Directives
;the NOP and SUB DI,SI are assembled
If 1
Nop
Nextif 0
Mov Ax,Dx
Nextif 1
Sub Di,Si
Endif
The ELSEIF directive can be thought of as "if the previous IF was
false and if the condition is true, then assemble the following
code." In other words, the conditional operand will only be
tested if the previous IF was false. ELSEIF has a single
conditional operand. Any number of ELSEIF's may follow an IF.
ELSEIF's are most useful for defining a sequential series of
source code blocks in situations where only one of the blocks will
be assembled and the remaining blocks skipped.
;the DEC AL is assembled
If 0
Nop
Elseif 1 ;previous IF=false and operand=true, true
Dec Al
Endif
;only the INC BP is assembled, the ELSEIF directives
;default to false because the first IF is true
If 1
Inc Bp
Elseif 1
Nop
Elseif 1
Call Near [Ax]
Endif
;only the NOP is assembled
If 0
Inc Bp
Elseif 1
Nop
Elseif 1
Call Near [Bx]
Endif
The ELSE directive is just like an ELSEIF directive where the
condition is always true. The source code after the ELSE is
automatically assembled if the previous IF was false, otherwise
the source code is skipped. Only a single ELSE should follow an
IF. ELSE's are used when a section of code should be assembled
either one way or another.
Conditional Directives 21
;the SUB WORD [DI],6 is assembled
If 0
Mov Word [Di],0
Else
Sub Word [Di],6
Endif
The NEXTIF, ELSEIF, and ELSE directives generally should not be
mixed together in a single conditional structure. The only
exception may be using ELSEIF's or a single ELSE after a NEXTIF,
or a single ELSE after an ELSEIF. Remember that all conditional
structures start with an IF and end with an ENDIF. The ENDIF must
come after any intermediary conditional directives (NEXTIF,
ELSEIF, and ELSE).
;the SUB DI,10 and SUB SI,30 are assembled
If 1
Sub Di,10
Nextif 0
Add Si,20
Else
Sub Si,30
Endif
;the MOV DL,AL is assembled
If 0
Mov Dl,Cl
Elseif 0
Mov Dl,Bl
Else
Mov Dl,Al
Endif
22 Nested Conditional Assembly
Nested Conditional Assembly
Conditional statements may be nested up to ten deep. An IF or IFN
following an IF, IFN, NEXTIF, ELSEIF, or ELSE, but before the
ENDIF, starts a nested conditional structure. The NEXTIF, ELSEIF,
ELSE, and ENDIF directives always match the last IF or IFN. The
nested conditional code continues until its ENDIF is reached.
;only the last SUB DX,DX is assembled, the
;remaining code is skipped because of the
;initial false IF; comments on conditional
;statements that say "true" or "false" are
;actually evaluated, comments that say "skipped"
;aren't evaluated because of a previous
;false conditional statement
If 0 ;false
Add Dx,Dx
Ifn 0 ;skipped
Add Ax,Ax
Else ;skipped
Sub Ax,Ax
Endif ;end of nested code
Else ;true
Sub Dx,Dx ;line is assembled
Endif
Nested Conditional Assembly 23
;... and a more complicated nesting example,
;only the ADD AX,AX is assembled
If 0 ;false
Nop
Elseif 0 ;false
Nop
Else ;true
If 0 ;false
Nop
Ifn 0 ;skipped
Nop
Nextif 0 ;skipped
Nop
Else ;skipped
Nop
Endif
Elseif 1 ;true
Ifn 1 ;false
Nop
Nextif 0 ;false
Nop
Nextif 1 ;true
If 1 ;true
Add Ax,Ax ;line is assembled
Else ;false
Nop
Endif
Endif
Elseif 1 ;false
Nop
Endif
Endif
24 Conditional Operators
Conditional Operators
Conditional operators return a true or false value after comparing
two immediate data operands. Conditional operators are used for
evaluating and comparing conditional operands.
Conditional operators check for ranges or particular values
through the use of: "<", ">", and "=". They work like normal
operators, except that they return either FFFFH for true or 0 for
false.
;the SHR CX is assembled, since one is equal
;to one; it may seem silly to write "1=1",
;but maybe it was originally "Parm=1", inside
;of a macro, where PARM is a macro parameter that
;may be different each time the macro is called
If 1=1
Shr Cx
Endif
;the SHR CX is assembled, only the 2<3 is true
If 2 = 3
Shr Ax
Nextif 2 > 3
Shr Bx
Nextif 2 < 3
Shr Cx
Endif
;the CLC is assembled; the condition is true
;because (2>2) = 0, (2=2) = 0FFFFH, so the
;condition is the same as 0 OR 0FFFFH, which is
;equal to 0FFFFH, which is true; this construction
;creates a "greater or equal to" condition;
;all the various numerical comparisons can be
;created using conditional and logical operators
If (2 > 2) Or (2 = 2)
Clc
Endif
Conditional Operand Testing 25
Conditional Operand Testing
The functions TYPE, VALUE, and SIZE are used to check for specific
operand qualities. Each of these functions return a 16 bit value
that corresponds to a particular attribute of its argument.
The type represents how the operand is interpreted (register,
immediate data, near label, etc.). The value may be a number to
distinguish a register from another registers, the location of a
label, or the actual value of an immediate data number. The size
is how many bits the register or memory location represents, or
the number of bits that an immediate data number can represented
by. The type and size work on a bit by bit basis, that is, a
particular bit represents a particular type or size. An operand
may be represented by more than one type or size (i.e. have
multiple bits set). Two operands are identical only if their
type, value, and size are all identical.
Operands can be tested for certain characteristics by comparing
the bit settings to those of known operands. It can be a bit
tricky to test for the exact conditions you want, some
experimentation may be necessary. For the most part, if the any
of the type or size bits match, the operands will be compatible in
size or type.
For the following examples, assume that P1 and P2 are macro
parameters passed to the conditional statement:
;the following is true only if P1 and P2 are
;identical, the equates are used to make it
;fit all on one line
P_Type Equ Type(P1) = Type(P2)
P_Size Equ Size(P1) = Size(P2)
P_Value Equ Value(P1) = Value(P2)
If P_Type And P_Size And P_Value
;the following is true only if P1 is a non-
;segment register (a segment register is not
;not necessarily compatible with a normal
;register); only matching bits will make the
;result non-zero (true), and only
;non-segment registers have matching bits
If Type(P1) And Type(Ax)
;the following is true only if P1 IS a
;segment register, the opposite of above
If Type(P1) And Type(Ds)
26 Conditional Operand Testing
;the following is true only if P1 is AX or
;AL; this statement is testing for equality,
;not just matching bits; a normal register
;wouldn't work because AX has an extra bit
;set (which defines it as the accumulator)
If Type(P1) = Type(Ax)
;the following is true only if P1 is AL; like
;above, the accumulator type is tested for, but
;also the size must be the same as CH
If (Type(P1) = Type(Ax)) And (Size(P1) = Size(Ch))
;you might think that the following is true if P1
;is any non-segment eight bit register, since it
;checks for compatible types and compatible sizes;
;unfortunately it doesn't necessarily work; the
;type and size comparisons each produce a bit
;pattern; those patterns individually, if
;compatible, are an arbitrary non-zero; there is
;no guarantee that these the two individually
;compatible bit patterns are compatible with
;each other
If (Type(P1) And Type(Dx)) And (Size(P1) And Size(Dh))
;instead you can write the previous statement in
;the following manner; this statement, like the
;above, tests the size and type for compatibility,
;but then compares the result to zero; the type
;and size comparisons now return FFFFH if they
;are false (equal to zero), and 0 if they are
;true; now the two results can then be compared;
;since we want a positive result to be true,
;rather than a negative one, the entire
;expression must be placed within a NOT
If Not((Type(P1) And Type(Dx)=0) And (Size(P1) And Size(Dh)=0))
;the above statement can more easily be written
;with the IFN directive as follows
Ifn (Type(P1) And Type(Dx)=0) And (Size(P1) And Size(Dh)=0)
More examples of conditional operand testing are provided under
Conditional Macros.
Macros 27
Macros
A macro is a type of programmer defined routine. A macro consists
of a symbol that has some number of source lines assigned to it.
The programmer creates a macro by assigning a section of code to a
symbol. Any time the assembler encounters the symbol as an
instruction, the source code assigned to it is inserted into the
program. A macro may be used any number of times and at any
location in the program. In addition, the macro may have some
number of "operands," which are passed as parameters to the
inserted source code. Macros are often used in conjunction with
conditional assembly to create routines that adjust to different
parameters.
Macros are useful for inserting sections of code that are used
several times in a single program. Macros are also used to define
a standard set of routines that are used by many different
programs. By including a file with commonly used macro
declarations, the programmer can use only those macros that are
needed by that particular program. Macros only create object code
by the source lines they insert, that is, the macro declarations
themselves do not take up any space in the assembled program.
28 Defining Macros
Defining Macros
Macros may be defined anywhere within the program, except inside
of other macro declarations. The MACRO directive starts a macro
declaration. The required symbol declaration becomes the name of
the macro. Any number of operands may follow the MACRO directive.
These operands are used to pass parameters into the macro.
Whenever the macro is invoked, the parameter names are replaced
(inside of the macro) by whatever corresponding operands where
placed after the macro name. The parameter names are local to the
macro and need only be unique within that macro, otherwise all the
normal restrictions to symbol declarations apply. The parameters
names should be single fields separated by commas (no expressions
or functional operands).
Any number of source lines may follow the MACRO directive. Macro
declarations are stored internally, and are thus limited by
memory. If the macro area becomes full, the assembly will
terminate and display the appropriate error message. The entire
source line, including all spaces, non-standard control
characters, and extended ASCII characters, are preserved
throughout the macro storage and expansion.
Symbols may be defined normally within macros. Symbols defined
within a macro are local and cannot be accessed outside of that
macro. The symbols need only be unique within that macro. Local
equates may be defined using the macro parameters.
All 8086 instructions and assembly directives may be used within
macros. Macros may also be invoked within other macros. You can
even have a macro call itself recursively. Conditional statements
within macros apply to the overall conditional structure of the
program, in other words, an ENDIF inside of a macro could be
matched to an IF that appeared sometime outside and before the
macro. Note that macros are not expanded if they are in false
conditional code, except for conditional macros, see Conditional
Macros.
A operand field inside of a macro may either be a parameter name,
one of the predefined operand types, a local symbol, or a global
symbol. Parameter names take precedence over all other fields and
are replaced before any interpretation occurs. Local symbols take
precedence over global symbols. When specifying parameter names,
if it is possible that the parameter will receive a nul string, it
is a good idea to put parenthesis around the name. This allows
the line to be parsed correctly if a nul parameter is passed.
Conditional statements can be used to test for valid parameters.
If a parameter is not valid, it can be flagged with the ERROR
directive.
A macro declaration is ended by the ENDM directive.
Defining Macros 29
;defines a macro to move a value into segment
;register, especially immediate date, since
;immediate data cannot be moved directly into
;a segment register
Mov_Seg Macro Segment_Reg, Location
Push Ax
Mov Ax, Location
Mov Segment_Reg, Ax
Pop Ax
Endm
;defines a macro to execute an interrupt, also
;if a function number is provided, it is placed
;in AH; if the interrupt number is not immediate
;data, it is flagged.
Interrupt Macro Int_Num, Func_Num
If Type(Int_Num) And Type(0)
Ifn Type(Func_Num) = Type()
Mov Ah, Func_Num
Endif
Int Int_Num
Else
Error 'Interrupt must be immediate data'
Endif
Endm
30 Invoking Macros
Invoking Macros
Macros are invoked by using the macro name as an instruction. Any
operands will be passed as parameters. The operands may be any
kind, of any length, including expressions and functional
operands. Parameters are assigned in the order in which they were
defined in the macro declaration. Extra operands are ignored,
missing parameters pass a nul string. A parameter may be skipped
and be assigned a nul string by placing a comma without an
operand.
Parameter names are blindly replaced in the macro source lines by
their passed parameters. Nul parameters simply remove the
parameter name. The resulting source line may be longer or
shorter than the original. Unnecessary spaces are removed from
the parameters, so they may not look exactly the same in the
source line as they did when they were first specified as
operands.
Macros are not normally expanded if the present source code is
being skipped because of a false conditional statement. Any
conditional statements within that macro will be ignored.
Conditional macros, on the other hand, are expanded under those
circumstances, see Conditional Macros.
Invoking Macros 31
;defines a macro to declare three bytes, any
;missing parameters are declared as zero
Dec_Bytes Macro Byte1, Byte2, Byte3
Ifn Type(Byte1) = Type()
Db Byte1
Else
Db 0
Endif
Ifn Type(Byte2) = Type()
Db Byte2
Else
Db 0
Endif
Ifn Type(Byte3) = Type()
Db Byte3
Else
Db 0
Endif
Endm
Dec_Bytes ;produces 000000
Dec_Bytes 1 ;produces 010000
Dec_Bytes ,2 ;produces 000200
Dec_Bytes ,,3 ;produces 000003
Dec_Bytes 1,2 ;produces 010200
Dec_Bytes ,2,3 ;produces 000203
Dec_Bytes 1,,3 ;produces 100003
Dec_Bytes 1,2,3 ;produces 010203
32 Nested Macros
Nested Macros
Macros may be nested up to ten deep. A macro invocation inside of
another macro works no differently than any other macro
invocation. When the nested macros finishes, the original macro
resumes. A macro may even call itself recursively, though, unless
the recursion is controlled by conditional statements, an error
will occur when the maximum nest level is exceeded.
Parameters may be passed to successive macro levels. Local
symbols within a macro cannot be accessed by any nested macros
within it.
;defines a macro that uses recursion to produce
;a specified number of single shift right
;instructions, the macro calls itself as long as
;the count parameter is greater than zero; note
;that the count cannot exceed nine (assuming it is
;not called from within another macro), otherwise
;the macros will nest too deeply
Shift_Right Macro Operand, Count
If Count > 0
Shr Operand
Shift_Right Operand, Count-1
Endif
Endm
Conditional Macros 33
Conditional Macros
Conditional macros are similar to normal macros. They are
declared with MACROC instead of MACRO. The purpose of conditional
macros are to create custom conditional statements. Conditional
macros do three things that normal macros don't: the line invoking
the macro is not listed (like like a conditional statement), the
macro expansion is not listed (by an implicit EXPAND-), and the
macros are expanded in false conditional code. Generally one
would declare the macro with just a single conditional line that
expresses the relationship that is desired.
;defines an "if the parameter doesn't exist" statement by
;testing to see if the type returned for the parameter
;is the same as the type returned for a nul operand
If_None Macroc Parameter
If Type(Parameter) = Type()
Endm
;defines an "if the parameter exists" statement
;by taking the opposite result of the declaration above
If_Exist Macroc Parameter
Ifn Type(Parameter) = Type()
Endm
;defines an "if the parameter is a byte" statement
;by testing if any of the same size bits are set in the
;size of the parameter and the size of a byte value
If_Byte Macroc Parameter
If Size(Parameter) And Size(Byte 0)
Endm
;defines an "if the sizes of the parameters are
;compatible" statement by testing for matching
;size bits
If_Compatible_Size Macroc Parameter1, Parameter2
If Size(Parameter1) And Size(Parameter2)
Endm
;defines an "if the parameters are identical"
;statement testing if the type, value, and size
;are identical; equates are used to simplify and
;shorten the final statement
If_Same Macroc Op1, Op2
Stype Equ Type(Op1) = Type(Op2)
Ssize Equ Size(Op1) = Size(Op2)
Svalue Equ Value(Op1) = Value(Op2)
If Stype And Ssize And Svalue
Endm
34 Listing of Macros
Listing of Macros
Macro expansions are listed like any other source line. The
special list indicator byte is a plus (+) in inserted macros
lines. The present macro nest level is displayed when the macro
is first invoked. This number is shown in the area normally
reserved for the object code. There is no way to tell when a
nested macro ends within another macro.
The listing of inserted macro lines may be globally suppressed or
enabled with the EXPAND- and EXPAND+ directives. The listing of
individual macros may also be controlled by these directives. If
EXPAND- and EXPAND+ directives appear in a macro, they only affect
that macro (and any nested macros). EXPAND- and EXPAND+ do not
have any effect if the source code is not otherwise being listed.
Note that EXPAND- and EXPAND+ only affect the listing of macros,
not the actual expansion of macros.
Errors occurring within macro expansions are treated normally,
except that the error message shows the last real line number and,
if in an included file, the name of the source file. The line
number is in parenthesis following the error message.
;defines a macro that adds the parameters
;together and puts the result in DX; this
;macro is never listed because of the
;EXPAND-
Adder Macro Parameter1, Parameter2
Expand-
Mov Dx,Parameter1
Add Dx,Parameter2
Endm
Data 35
Data
Data that is used by the program during execution must be placed
in the program by declaration. Data that is declared includes
things like numbers and strings. This is in contrast to the
declaration of macros and equates which are only used when the
program is assembled. The DB, DW, and DS directives are used to
make data declarations.
DB is used to declare byte values, strings, words, and
combinations of all three. If a symbol is declared with the DB
directive, it becomes an eight bit memory reference label. The
data declared by the DB may be accessed through the label. Values
are declared as bytes if possible, only if they must be words are
they declared as words. The BYTE and WORD functions may be used
to explicitly set the number bits that DB data is declared as.
DW is used to declare word values. If a symbol is declared with
the DW directive, it becomes a sixteen bit memory reference label.
The data declared by the DW may be accessed through the label.
Values are always declared as words, even if they may be bytes.
DS is used to declare any number of identical bytes. If a symbol
is declared with the DS directive, the it becomes a memory
reference label with no size. The size should be specified
whenever this label is accessed (via the size functions BYTE,
WORD, DWORD, etc.). The LABEL directive may be used to declare a
label of a particular type and size immediately before the DS.
Word values are always stored low byte first with the exception of
two byte strings. Assuming '1' = 31H and 'B' = 42H, the hex
number 3142H will be stored as 4231H, though '1B' will be stored
as 3142H. The reverse format is how word numbers should be
stored. If for some reason a word value is stored as two separate
bytes (using DB), the low byte should always be stored first,
otherwise the number will be backwards for arithmetic operations.
Declarations may be made anywhere in the program. Since
declarations produce non-executable object code, they should not
be placed in a location where they might be interpreted as part of
the code. Branch the program around declarations, or put them at
the end of the program or routine, after the executable code.
Examples of data declarations:
;declare a byte
Db -5
;declare a byte and then a word value
Db Byte 0, Word 0
;... or just
Db 0, Word 0
36 Data
;declare a string
Db 'This is the string'
;declare some words
Dw 0, 1, 2, 3, 65533, 65534, 65535
;the following declaration can be accessed through VALUES
Values Db 100,-20, 36/10, 0, 010100110b
;this instruction accesses the numbers
;in VALUES above based on an index in BX
Mov Al, [Values + Bx] ;load number
;declare storage
Ds 10 ;ten bytes of 00
Ds 100, 0ffh ;a hundred bytes of FFH
Assembly Directives 37
Assembly Directives
Assembly directives are instructions to control the assembly, they
do not encode into 8086 machine language instructions, though some
of the directives do produce object code. Assembly directives are
implemented the same way as normal instructions.
This section describes all the assembly directives. Most of the
directives are also described in sections pertinent to their
operation.
The major categories of assembly directives are those that are
used to declare symbols (EQU, LABEL, ORG), those that declare data
(DB, DS, DW), those that declare procedures and macros (PROC,
ENDP, MACRO, MACROC, ENDM), those used to control conditional
assembly (ELSE, ELSEIF, ENDIF, IF, IFN, NEXTIF), those that
control the assembly listing (EXPAND+, EXPAND-, LINSIZE, LIST+,
LIST-, PAGE, PAGE+, PAGE-, PAGESIZE, SUBTITLE, SYMDUMP+, SYMDUMP-,
TITLE), those that control error flagging and detection (ERROR,
ERRORMAX, FLAGALL+, FLAGALL-, JUMP+, JUMP-, UNUSED+, UNUSED-), and
some miscellaneous ones (INCLUDE, RESETC).
******************************************************************
DB value/string, ...
Declare byte.
Places literal bytes of data into the assembled code.
DB may have any number of operands, as long as they fit on the
line. The value of each operand is placed sequentially into the
assembled code. The operands can be immediate data or strings.
Immediate data operands are declared as bytes if possible,
otherwise they are declared as words. Strings are inserted just
as they appear (minus the string delimiters).
See Data.
;the following declares a sentence with its
;length preceding it, including a carriage
;return and linefeed at the end of the sentence;
;the BYTE function is needed to make the length
;an explicit eight bit value
A
Db Byte(Offset B - Offset A - 1),'The sentence.',10,13
B
;this declares a byte FFH and then a word FFFFH
Db -1, Word -1
38 Assembly Directives
******************************************************************
DS bytes [, value]
Declare storage.
Places some number of identically initialized bytes into the
assembled code.
DS can have one or two operands. The first operand is the number
of bytes to declare and the second is the value that the storage
should be initialized to. The initialization value is optional,
and, if absent, the storage is initialized to zero. The number of
bytes to declare must be immediate data (0 to 65535). The
initialization value must be eight bit immediate data.
See Data.
;declare a thousand bytes of FFH
Ds 1000, 0ffh
******************************************************************
DW value, ...
Declare word.
Places literal words of data into the assembled code.
DW can have any number of operands, as long as they fit on the
line. The value of each operand is placed sequentially into the
assembled code. The operands must be immediate data. The
operands are always declared as words, even if they could be
bytes.
See Data.
;this sort of construction can be useful
;for creation a table of addresses, note
;that this particular example would work
;equally well with DB
Dw Offset Subrt1, Offset Subrt2
******************************************************************
ELSE
Conditional "else."
Assembles the following source code only if the previous IF
directive was false.
Requires no operands.
Assembly Directives 39
See Conditional Assembly.
;the code after the ELSE is carried out
;if NUMBER is not greater than 10
If Number > 10
Mov Ax, Bx
Else
Mov Bx, Ax
Endif
******************************************************************
ELSEIF condition
Conditional "else if."
Assembles the following source code only if the previous IF
directive was false and the condition is true.
ELSEIF requires a single immediate data operand. This operand is
the condition to test.
See Conditional Assembly.
;only one of the following are true:
;if OPTION is equal to zero, CALL SUBRT1 is
;assembled; if OPTION is equal to one,
;CALL SUBRT2 is assembled; if OPTION is equal
;to two, CALL SUBRT3 is assembled
If Option=0
Call Subrt1
Elseif Option=1
Call Subrt2
Elseif Option=2
Call Subrt3
Endif
******************************************************************
ENDIF
End of conditional structure.
Finishes a conditional structure started by an IF directive.
Requires no operands.
See Conditional Assembly.
40 Assembly Directives
;ENDIF finishes the conditional structure,
;so the CLC is assembled no matter what
If Type(Parameter)=Type(Ax)
Sub Ax, Ax
Endif
Clc
******************************************************************
ENDM
End of macro.
Finishes a macro declaration started by a MACRO or MACROC
directive.
Requires no operands.
See Macros.
;the ENDM finishes the rather simple declaration
;of the macro NUL_INST
Nul_Inst Macro
Nop
Endm
******************************************************************
ENDP
End of procedure.
Finishes a procedure declaration started by a PROC directive.
Requires no operands.
See Procedures.
;the ENDP finishes the declaration of the
;procedure SUBRT
Subrt Proc Near
Xchg Ax, [Si]
Ret
Endp
******************************************************************
EQU value
Equate a value.
Assembly Directives 41
Defines a symbol that may be used anywhere in place of a specified
value.
EQU requires a single immediate data operand and the symbol to be
equated. The operand becomes equated to the symbol.
EQU is useful for making the source code more readable by
replacing arbitrary numbers with meaningful symbols. The value of
the equate generally should not reference any symbols that have
not been defined yet in the source code. This means that the
value should not contain a forward reference to another equate, or
use OFFSET when its argument has not yet been defined.
See Symbols.
;equate the number 50 times 20, or 1000, to the
;symbol NUMBER, and then move NUMBER into AX
Number Equ 50*20
Mov Ax, Number
******************************************************************
ERROR message
Programmer defined error.
Causes an error to occur using the specified message.
ERROR requires a single string operand. This operand becomes the
error message.
No line is displayed with the error message, the listing of the
statement itself is suppressed. The error is included in total
number of errors at the end of the program. ERROR is useful for
flagging invalid macro parameters.
;defines a macro that checks for a missing operand;
;if the macro is invoked with the operand is missing,
;an error is displayed using an ERROR directive
Mover Macro Op1
If Type(Op1) = Type()
Error 'Missing operand'
Endif
Endm
;this will cause the error
Mover ;invoked with no operands
42 Assembly Directives
******************************************************************
ERRORMAX number
Maximum errors.
Places an upper limit on the number of errors and comments
occurring before the assembly is halted.
ERRORMAX requires a single immediate data operand. This operand
becomes the new number of maximum allowed errors.
The default is 65535. Note that both errors and comments are
counted.
;set the number of allowed errors to ten, if a tenth error
;or comment ever occurs, the assembly will be terminated
Errormax 10
******************************************************************
EXPAND+
EXPAND-
List macro expansions.
When activated (EXPAND+), lines resulting from a macro expansion
will be listed. When deactivated (EXPAND-), lines resulting from
a macro expansion will not be listed, only the line containing the
macro invocation will be visible.
Requires no operands.
The default is EXPAND+. EXPAND+ and EXPAND- directives that are
within macros only apply to those macros. Macros will not be
listed regardless of the EXPAND+ and EXPAND- directives if the
source code is not otherwise being listed.
See Macros and Assembly Listing.
;macro expansions are globally listed because
;of the EXPAND+, except the defined macro TERMINATE
;explicitly suppresses only its own listing
Expand+
Terminate Macro
Expand-
Mov Ah, 4ch
Int 21h
Endm
Assembly Directives 43
******************************************************************
FLAGALL+
FLAGALL-
Undefined symbol flagging.
When activated (FLAGALL+), an undefined symbol is flagged each
time it is used, even if it has been flagged before. When
deactivated (FLAGALL-), an undefined symbol is only flagged the
first time it is used.
Requires no operands.
The default is FLAGALL-.
;assuming BADSYM is undefined, it is flagged when
;it is moved to AX and BX, but not when it is
;moved to CX or DX, since it has been flagged
;previously and because of the FLAGALL-
Flagall+
Mov Ax, Badsym
Mov Bx, Badsym
Flagall-
Mov Cx, Badsym
Mov Dx, Badsym
******************************************************************
IF condition
Conditional "if."
Assembles the following source code only if the condition is true.
IF requires a single immediate data operand. This operand is the
condition to test.
The IF directive starts a conditional structure. See Conditional
Assembly.
;if COND is zero, the IN AX,DX will be assembled
If Not(Cond)
In Ax, Dx
Endif
******************************************************************
IFN condition
Conditional "if not."
Assembles the following source code only if the condition is
false.
44 Assembly Directives
IFN requires a single immediate data operand. This operand is the
condition to test.
The IFN directive starts a conditional structure. IFN is the
opposite of IF. See Conditional Assembly.
;if COND is zero, the OUT DX,AX will be assembled
If Cond
Out Dx, Ax
Endif
******************************************************************
INCLUDE file
Include source file.
The specified file is inserted into the main source code
immediately after the INCLUDE directive.
INCLUDE requires a single string operand. This operand should
contain the name of the file to insert. If no path is specified,
the main source file path is used. If no extension is specified,
the extension of ASM is used.
The included source code is not treated any differently than the
rest of the program. Included files may NOT be nested, which
means that the file being inserted may not contain any INCLUDE
directives. Neither may INCLUDE's be used within macros. INCLUDE
is useful for inserting source code used by many different
programs, like standard macro declarations. INCLUDE can also be
used to break up a source file into several smaller chunks, if,
for instance, your text editor cannot handle the entire source
file at once.
;the following directive inserts the file
;INCLUDE.INC, the source drive and path are
;used
Include 'Source.Inc'
******************************************************************
JUMP+
JUMP-
Short jump checking.
When activated (JUMP+), all long near jump instructions will be
flagged if a short near jump could be substituted. When
deactivated (JUMP-), long jumps that could be short jumps are not
flagged.
Requires no operands.
Assembly Directives 45
The default is JUMP-. Substituting a short jump for a long jump
does not logically change the program, but does make the assembled
code one byte shorter.
;both of the following jumps could be
;JMPS (a short unconditional jump); the
;first JMP LABEL is not flagged, the
;second one is
Jump-
Jmp Label
Jump+
Jmp Label
Label
******************************************************************
LABEL type
Label declaration.
Defines a branch or memory reference label using the present
location counter.
LABEL requires a single operand and a symbol to be defined. The
operand NEAR or FAR is used for branch locations. The operand
BYTE, WORD, or DWORD is used for memory references of eight,
sixteen, or thirty-two bit sizes, respectively.
Explicitly defining a symbol as NEAR has the same effect as
placing a symbol on an otherwise empty line or a line with some
sort of operation (not a data declaration). Explicitly declaring
a symbol as BYTE or WORD has the same effect as placing a symbol
on a byte (DB) or word (DW) data declaration. LABEL can be used
in conjunction with the ORG directive to define labels independent
of the actual code being assembled.
See Symbols.
;this label ...
Bran1 Label Near
;...is the same type as
Bran2 Mov Ds, Dx
;and this ...
Dat1 Label Word
;... produces the same sort of label as ...
Dat2 Dw ?
46 Assembly Directives
;the following causes MEM_SIZE to point at the word
;in program segment prefix that tells how many bytes
;are available in the segment; if you use this method
;to define any labels, make sure to reset the location
;counter back to its proper value before defining any
;other normal labels in the program
Org 6
Mem_Size Label Word
******************************************************************
LINESIZE [length] [, code, ...]
List line length.
Sets the maximum number of characters in each list line.
The optional first operand is the list line length. The remaining
optional eight bit immediate data operands are printer codes.
These printer codes are sent directly to the printer if the list
file is PRN.
The default is 79. The length must be in the range 45 to 158.
The number of characters per line should only be set once in a
program, though multiple LINESIZE directives may be used to send
several bunches of printer codes. If a list line would come out
any longer than specified by the LINESIZE, it will be truncated.
PAGESIZE can also be used to set the number of characters per
line.
See Assembly Listing.
;set up for IBM Graphics printer compressed font, the
;printer code (15) is sent if PRN is the list file
Linesize 131, 15
******************************************************************
LIST+
LIST-
Assembly listing.
When activated (LIST+), a listing of the program will be
generated. When deactivated (LIST-), no listing will be
generated.
Requires no operands.
Assembly Directives 47
If a list file was specified at the start of the program, the
default is LIST+. If no list file was specified, no list will be
generated (regardless of any LIST+ or LIST- directives). LIST+
and LIST- directives that are within included files only affect
those files, so you could, for instance, place a LIST- at the
start of a source file to be included and just have the listing of
that file suppressed. LIST+ and LIST- directives are useful for
selectively listing isolated sections of the source code.
See Assembly Listing.
;turn list off, NOP's are not listed
List-
Nop
Nop
;turn list on, NOP's are listed
List+
Nop
Nop
******************************************************************
MACRO [parameter, ...]
Macro declaration.
Begins a macro declaration that will be finished by the ENDM
directive.
MACRO may have up to ten operands. These operands must be unique
symbols within the macro declaration. The operands become the
names of any parameters passed to the macro upon invocation. A
symbol declaration to name the macro is also required.
See Macros.
;defines the macro LOAD_DS, the MACRO
;directive starts the declaration
Load_DS Macro Op1
Mov Ax, Op1
Mov Ds, Ax
Endm
******************************************************************
MACROC [parameter, ...]
Conditional macro declaration.
Begins a conditional macro declaration that will be finished by
the ENDM directive.
48 Assembly Directives
MACROC may have up to ten operands. These operands must be unique
symbols within the macro declaration. The operands become the
names of any parameters passed to the macro upon invocation. A
symbol declaration to name the macro is also required.
See Conditional Macros.
;defines a conditional directive TOO_SMALL
;that is false if the operand is above ten,
;i.e. "if not above ten then do the following"
Too_Small Macroc Op1
Ifn Op1 > 10
Endm
;with the above declaration, the ADD AX,AX
;will be assembled because 11 is above 10
Too_Small 11
Sub Ax, Ax
Else
Add Ax, Ax
Endif
******************************************************************
NEXTIF condition
Conditional "if", same level.
Finishes the present conditional block and starts a new one.
Assembles the following source code only if the condition is true.
NEXTIF requires a single immediate data operand. This operand is
the condition to test.
See Conditional Assembly.
;any or all of the following may be true:
;if OPTION is equal to ten, CALL SUBRT1 is
;assembled; if OPTION is less than ten,
;CALL SUBRT2 is assembled; if OPTION is greater
;than ten, CALL SUBRT3 is assembled
If Option=10
Call Subrt1
Nextif Option<10
Call Subrt2
Nextif Option>10
Call Subrt3
Endif
Assembly Directives 49
******************************************************************
ORG value
Origin.
Sets the location counter to the specified value.
ORG requires a single immediate data operand. This operand
becomes the new location counter value. If the operand is signed,
the value is treated as a displacement to the present location.
The default is 100H, which is the starting offset required for COM
programs. ORG affects the location assigned to labels. ORG can
be used to set the offset of specially defined labels.
;this declares three consecutive memory labels, note
;that these declarations only create the labels and do
;not allow space for them in the object code, this sort
;of thing could be done at the end of the program to
;create uninitialized data locations in memory
Data1 Label Word
Org $+2
Data2 Label Word
Org $+2
Data3 Label Word
Org $+2
;remember that signed numbers are treated as displacements
Org 2 ;(unsigned, absolute)
Symbol1 ;this symbol points to [0002]
Org +2 ;(signed, displacement)
Symbol2 ;this symbol points to [0004], two past the
;location above
******************************************************************
PAGE [page|subtitle]
PAGE page [, subtitle]
New page.
Starts a new list page regardless of whether paging is on or off,
or what the size of the previous page was.
PAGE may have none, one, or two operands. If the first operand is
immediate data, it becomes the new page number. If the first
operand a string, it becomes the new page subtitle. If both a
page number and a subtitle are included, the page number must come
first.
50 Assembly Directives
If the page number is not specified, the previous page number is
incremented. If the subtitle is not included, the subtitle from
the previous page is used. PAGE can be used in conjunction with
automatic paging (PAGE+) to start a new section of the code with a
new subtitle.
See Assembly Listing.
;start a new page and set the page number
;to ten and the subtitle to "Page ten"
Page 10, 'Page ten'
******************************************************************
PAGE+ [page|subtitle]
PAGE+ page [, subtitle]
PAGE-
Automatic paging.
When automatic paging is activated (PAGE+), a new page is started
after every number of lines specified by the PAGESIZE directive
(default 60). When automatic paging is not activated (PAGE-), no
paging is done, except by the PAGE directive. PAGE+ automatically
starts a new page if there are operands (i.e. a page number,
subtitle, or both).
PAGE+ has operands identical to those of PAGE, see PAGE above.
PAGE- requires no operands.
Default is PAGE-. Paging can make the listing of a program look
better if a hard copy is printed out on separate pages.
See Assembly Listing.
;activate auto paging, start a new page, and
;set the subtitle to "Start of Paging"
Page+ 'Start of Paging'
******************************************************************
PAGESIZE lines [, characters ]
Page size.
Sets the lines per page and the maximum number of characters per
line. The lines per page affect the number lines output before a
new page is started when automatic paging (PAGE+) is active. The
characters per line affect the final length of each list line.
PAGESIZE may have one or two immediate data operands. The first
operand becomes the number of lines per page. The second operand
is optional and is the number of characters per line.
Assembly Directives 51
The default lines per page is 60. The default characters per line
is 79. The lines per page must be in the range 15 to 255 and the
characters per line must be in the range 45 to 158. The number of
lines per page and the number of characters per line should only
be set once in a program. The number of characters per line can
also be set with LINESIZE.
;this makes for very long pages
Pagesize 200
;the following two lines would have the same effect,
Pagesize ,50 ;note that the first operand is nul
;Linsize 50 ;characters per line should only be set once
******************************************************************
PROC type
Procedure declaration.
Begin a procedure declaration that will be finished by the ENDP
directive.
PROC requires a single operand. This operand is NEAR for near
procedures and FAR for far procedures.
Far procedures should only be used for routines that will be
called by other programs or are called indirectly. Far procedures
cannot be called locally via a CALL instruction. The type of
procedure determines how the returns (RET instructions) within the
procedure will be encoded.
See Procedures.
;the procedure ORRER is defined, the PROC
;directive starts the declaration
Orrer Proc Near
Or Cx, 10101b
Ret
Endp
******************************************************************
RESETC [count] [,checksum]
Reset counter.
Resets the counter ($COUNT) and counter checksum ($SUM).
52 Assembly Directives
RESETC may have none, one, or two immediate data operands. Both
operands are optional. If the first operand is present, it
becomes the new count value. If the second operand is present, it
becomes the new checksum value. If an operand is missing, zero is
used.
The new values take effect on the line after the RESETC directive.
This directive does not affect the program byte count ($SIZE) or
checksum ($CHKSUM).
Resetc ;set count and checksum to zero
Mov Ax, $Count ;will load zero to AX
Resetc ,20 ;default (zero) for count, 20 for checksum
Mov Ax, $Sum ;will load 20 to AX
******************************************************************
SUBTITLE subtitle
Program subtitle.
Defines the page subtitle for all subsequent pages.
SUBTITLE requires a single string operand. The operand becomes
the subtitle.
Note that SUBTITLE sets the subtitle for all pages following the
present one, not the page in which the SUBTITLE directive appears.
The PAGE, PAGE+, and TITLE directives can also be used to set the
subtitle.
See Assembly Listing.
;set the subtitle of the following pages
;to "Input and Output Routines"
Subtitle 'Input and Output Routines'
******************************************************************
SYMDUMP+
SYMDUMP-
Symbol table dump.
When activated (SYMDUMP+), the symbol table will be displayed at
the end of the listing. When not activated (SYMDUMP-), the symbol
table will not be displayed.
Requires no operands.
The default is SYMDUMP-. There is only one symbol dump at the end
of the program, i.e. there is no reason to turn the symbol table
dump on and then turn it off later.
Assembly Directives 53
See Symbol Table Listing.
;enable symbol dump at the end
;of the program
Symdump+
******************************************************************
TITLE title [,subtitle]
Program title.
Defines the page title for the entire program listing. The
starting page subtitle may also be specified.
TITLE requires one or two operands. The first operand becomes the
program title. The optional second operand becomes the subtitle.
Both operands must be strings.
Only one TITLE directive is valid for the entire program. The
TITLE directive is the only way to set the subtitle on the first
page header, since SUBTITLE takes effect on the next page
following the directive and PAGE and PAGE+ automatically start a
new page.
See Assembly Listing.
;set the program title to "Holy Cow" and the
;initial subtitle to "Initialize"
Title 'Holy Cow', 'Initialize'
******************************************************************
UNUSED+
UNUSED-
Unused symbol flagging.
When active (UNUSED+), all symbols that were never accessed will
be flagged. When not active (UNUSED-), unused symbols will not be
flagged.
Requires no operands.
Used to inform the programmer of unnecessary labels, routines,
etc. Unused macro declarations are never flagged. The default is
UNUSED-.
54 Assembly Directives
;assuming the near labels SYM1 and SYM2 were
;never accessed, SYM1 is flagged and SYM2 isn't
Unused-
Sym1
Unused+
Sym2
******************************************************************
Functional Operands 55
Functional Operands
Functional operands modify another operand passed as an argument.
Functional operands serve two general purposes: first to change a
characteristic of an operand but still use it in more or less the
same way, and second to isolate a specific aspect of an operand.
All functional operands take another operand as an argument and
can be used anywhere in place of a normal operand.
The major categories of functional operands are those that set the
size of its argument (ANYSIZE, BYTE, DWORD, QWORD, TBYTE, WORD),
those that change the type of its argument (FAR, NEAR), those that
change the value of its argument (NEG, NOT), and those that are
used to access specific qualities of its argument (OFFSET, SIZE,
TYPE, VALUE).
******************************************************************
ANYSIZE
Size any.
Set the size of its argument to all allowable sizes.
Its argument must be a memory operand or immediate data. Can also
be used with the LABEL directive.
;the following two statements do not
;conflict because of the ANYSIZE below
Mov Bx, Data ;move 16 bits
Add Data, Al ;add 8 bits
Data Label Anysize ;data label
Dw ? ;declare space for data
******************************************************************
BYTE
Size byte.
Set the size of its argument to byte size (8 bit).
Its argument must be a memory operand or immediate data. Can also
be used with the LABEL directive. Used mainly to declare the
number of bits acted upon in an operation if the operation would
be ambiguous otherwise.
;the size of [SI] would be ambiguous
Mov Byte [Si], 0 ;perform an 8 bit move
56 Functional Operands
******************************************************************
DWORD
Size double word.
Set the size of its argument to double word size (32 bit).
Its argument must be a memory operand or immediate data. Can also
be used with the LABEL directive. Used mainly to declare the
number of bits acted upon in an operation if the operation would
be ambiguous otherwise.
;make an intersegment call
Call Routine_Location ;call routine
Routine_Location Label Dword ;the location is 367A:6374
Dw 06374h ;offset
Dw 0367ah ;segment
******************************************************************
FAR
Type far label.
Set the type of its argument to far label.
Its argument must be a near label, far label, or memory operand.
If its argument is a near or far label, the label is simply
converted to a far label. If its argument is a memory operand,
FAR has the same effect as the DWORD function. This allows FAR to
be used in specifying indirect intersegment branching. FAR is
mainly used to declare a far procedure.
;execute an intersegment call, [BX] must point to a location
;containing the segment and offset of the subroutine to execute
Call Far [Bx] ;transfer control to routine
;declare a rather insignificant far procedure, cannot
;be called directly, but may be an interrupt handler
Subrt Proc Far ;make far procedure
Ret ;return, don't do anything
Endp ;end of declaration
******************************************************************
NEAR
Type near label.
Set the type of its argument to near label.
Functional Operands 57
Its argument must be a near label, far label, memory operand, or
immediate data. If its argument is a near or far label or
immediate data, the operand is simply converted to a near label.
If its argument is a memory operand, NEAR has the same effect as
the WORD function. This allows NEAR to be used in specifying
indirect same segment branching. NEAR is mainly used to declare a
near procedure.
;execute a same segment call, DATA must point to a location
;containing the offset of the subroutine to execute
Call Near Data ;transfer control to routine
Data Ds 2 ;two bytes of storage (offset)
;declare a near procedure that doubles AX
Double Proc Near ;make near procedure
Sal Ax ;double AX
Ret ;return
Endp ;end of procedure
;NEAR can be used to jump to a literal location
Jmp Near 100h ;branch to start of program
******************************************************************
NEG
Negate value.
Perform an arithmetic negate on the value of its argument.
Its argument must be immediate data. Acts the same as a preceding
sign, except that the validity of the result is not checked.
;the following two statements produce the same code
Mov Dx, Neg 1 ;load minus one
Mov Dx, -1 ;load minus one
;the following statement is really an undetected error
Mov Dx, Neg 40000 ;-40000 cannot be represented with 16 bits
******************************************************************
NOT
Logical not of value.
Perform a logical not on the value of its argument.
Its argument must be immediate data.
58 Functional Operands
;the following two statements produce the same code
Mov Dh, Not 10101010b ;load 55H
Mov Dh, 01010101b ;load 55H
******************************************************************
OFFSET
Offset of label.
Return the offset of its argument.
Its argument must be a near, far, or memory label. The offset, or
location, is returned as 16 bit immediate data. Is mainly used by
sections of code or individual routines which access data that may
be any length (like strings of characters).
;put message location in SI
Mov Si, Offset Start ;location
;put message length in CX
Mov Cx, Offset End - Offset Start ;size
Start Db 'This is the message' ;message data
End ;end of message marker
******************************************************************
QWORD
Size quadruple word.
Set the size of its argument to quadruple word (64 bit).
Its argument must be a memory operand. Not fully implemented,
will be used for 8087 support.
******************************************************************
SIZE
Size of operand.
Return the size of its argument.
Its argument may be anything. The size is returned as 16 bit
immediate data for comparison with the size of other operands.
See Conditional Operand Testing.
;the NOP is assembled if the sizes are identical
If Size Ax = Size Symbol ;compare sizes
Nop ;code if true
Endif ;end of conditional
Functional Operands 59
******************************************************************
TBYTE
Size ten byte.
Set the size of its argument to ten bytes (80 bit).
Its argument must be a memory operand. Not fully implemented,
will be used for 8087 support.
******************************************************************
TYPE
Type of operand.
Return the type of its argument.
Its argument may be anything. The type is returned as 16 bit
immediate data for comparison with the type of other operands.
See Conditional Operand Testing.
;the NOP is assembled if the types are identical
If Type Ax = Type Symbol ;compare types
Nop ;code if true
Endif ;end of conditional
******************************************************************
WORD
Size word.
Set the size of its argument to word (16 bit).
Its argument must be a memory operand or immediate data. Can also
be used with the LABEL directive. Used mainly to declare the
number of bits acted upon in an operation if the operation would
be ambiguous otherwise.
;the size of [BX+SI-10] would be ambiguous
Mov Word [Bx+Si-10], 0 ;perform a 16 bit move
******************************************************************
VALUE
Value of operand.
Return the value of its argument.
60 Functional Operands
Its argument may be anything. The value is returned as 16 bit
immediate data for comparison with the value of other operands.
See Conditional Operand Testing.
;the NOP is assembled if the values are identical
If Value Ax = Value Symbol ;compare sizes
Nop ;code if true
Endif ;end of conditional
******************************************************************
Assembly Constants 61
Assembly Constants
Assembly constants are special symbols that are interpreted into
immediate data during assembly. Assembly constants may be used
anywhere in place of immediate data. Beware that these constants
can cause an otherwise unexplained phase errors when used with
instructions that directly manipulate the the location counter,
like ORG. Care should also be taken when using assembly constants
with assembly directives that must control the assembly based on a
value. Assembly constants may always be safely used as operands
for 8086 instructions and in byte and word declarations (DB and
DW).
All symbols starting with a dollar sign are reserved as assembly
constants.
******************************************************************
$
Present location.
Returns the present value of the location counter. Same as $LOC.
May be safely used with the ORG directive. 16 bit.
;declares two memory labels that are ten bytes from each other
Data_Area1 Label Byte ;first label
Org $ + 10 ;advance location counter
Data_Area2 Label Byte ;second label
******************************************************************
$CHKSUM
Program checksum.
Returns the byte checksum of the object code up to and including
the previous source line. 8 bit.
******************************************************************
$COUNT
Byte count.
Returns the number of bytes of code since the beginning of the
program or the last RESETC directive. 16 bit.
62 Assembly Constants
;branch around the string and then load its size
Jmps Continue ;skip string
Resetc ;reset counter
Db 'Which way did he go?' ;string declaration
Continue ;continue execution
Mov Cx, $Count ;load byte count
******************************************************************
$DATE1
Month and day.
Returns the present day and month in the system format. The high
byte is the month (1 to 12) and the low byte is the day (1 to 31).
16 bit.
******************************************************************
$DATE2
Year.
Returns the present year in the system format. The value is 1980
to 2099. 16 bit.
******************************************************************
$LOC
Present location.
Returns the present value of the location counter. Same as $.
May be safely used with the ORG directive.
******************************************************************
$SIZE
Program size.
Returns the total size of the assembled program in bytes. 16 bit.
;load the size of the program into AX
Mov Ax, $Size ;load size
******************************************************************
$SUM
Counter checksum.
Assembly Constants 63
Returns the byte checksum of the object code up to and including
the previous source line since the beginning of the program or the
last RESETC. 8 bit.
******************************************************************
$TIME1
Second and 1/100 second.
Returns the present second and 1/100 second in the system format.
The high byte is the second (0 to 59) and the low byte is the
1/100 second (0 to 99). 16 bit.
******************************************************************
$TIME2
Hour and minute.
Returns the present hour and minute in the system format. The
high byte is the hour (0 to 23) and the low byte is the minute (0
to 59). 16 bit.
******************************************************************
$VERSION
Assembler version.
Returns the version number of the assembler. The high byte is the
minor version number and the low byte is the major version number.
;if assembling with WASM 2.14, AL get 2 and AH gets 14
Mov Ax, $Version
******************************************************************
64 Reserved Symbols
Reserved Symbols
The following are guidelines for what not to use as symbols. All
of these symbols have special meaning to WASM:
AX AL ES BYTE OR
CX CL CS WORD AND
DX DL SS DWORD XOR
BX BL DS QWORD MOD
SP AH NOT TBYTE SIZE
BP CH OFFSET ANYSIZE TYPE
SI DH NEAR ST VALUE
DI BH FAR NEG
A single question mark is also a reserved symbol. All fields
beginning with 0 to 9 are reserved for numbers. All fields
starting with a dollar sign ($) are reserved for assembly
constants. The following characters should never be used in
symbols: control characters (ASCII 0 to 31), spaces, commas; and
also any of the following: ; + - * = ' / \ ( ) < > [ ] Macros
should be unique from all other instructions, rather than the
special symbols above. It is recommended that programmer defined
symbols start with a letter and consist of only letters, numbers,
and underscores.
Assembly Listing 65
Assembly Listing
The assembly listing is a comprehensive trace of the assembly and
can be useful in debugging or making a hard copy of a program. A
listing is only generated if a list file is specified. The
assembly is speeded up if no list is generated. A listing can be
started or stopped with LIST+ and LIST- (these directives are
ignored if no list file is specified). The listing of macro
expansion lines can be enabled with EXPAND+ (the default), or
disabled with the EXPAND-. Also a listing of the symbol table
will be generated if a SYMDUMP+ is included somewhere in the
program (see Symbol Table Listing).
List directives within an included file only apply to the listing
of that file, and expand directives within a macro only apply to
the expansion of that macro. This means you can place a LIST- at
the start of an included file to suppress the listing of just that
file. You can use an EXPAND- similarly to create a macro that is
never expanded.
The listing may be divided up into pages. An individual page can
be started with PAGE. Automatic paging can be turned on with
PAGE+ and turned off with PAGE- (the default). The default page
size is 60 lines (which includes a five line page header). The
page size can be modified with PAGESIZE.
Each list page starts with a formfeed (ASCII 12) and a list
header. The formfeed is not included on the first page or on any
pages of a listing sent to CON. The list header consists of a
programmer defined title and subtitle, the name of the main source
file, the page number, the time and date, columnar headings for
the list lines, and the assembler version.
The title and subtitle are left justified in lines one and two
respectively. Only one title applies for an entire assembly
listing. Both the title and subtitle can be set with TITLE. The
subtitle can also be set with SUBTITLE, PAGE, and PAGE+.
The source file name is displayed with the present page number,
separated by a pair of dashes, right justified on the first line
(opposite to the title). Only the main source file name is
displayed (never any included file names). The page number starts
at one and increments with each page. The page number is never
directly based on the pages within a source file (unlike list line
numbers). The page number can be set with PAGE and PAGE+.
The time and date are right justified on the second line (opposite
to the subtitle).
66 Assembly Listing
The columnar headings and the assembler version follow a blank
line after the first two lines of the header (they are on line
four). In the columnar list headings: Loc stands for location
counter, Obj stands for object code, Line stands for line number,
and Source stands for source code. The assembler version is
justified to the right of the headings.
The listing starts after another blank line (i.e. the sixth line
of the page). Each list line contains the location counter value
(in hex), the object code for that line (also in hex), the source
line number, a special indicator byte, and the source line itself.
The location counter is not displayed if the line is blank or the
location is not relevant to the instruction contained in that
source line.
No object code will be displayed if, of course, none is generated
by the source line. Some instructions (DS) never display their
object code. Procedure (PROC) and End-Procedure (ENDP) directives
display the present procedure nest level instead. Macros display
the present macro nest level.
The line number is always the actual line number within the source
file. Included source files maintain their own line numbering.
You can use this number in your text editor to locate the line
within its file. Since macro expansion lines are not in the
source file, no line number is displayed.
The special indicator byte is a plus (+) for macro expansion
lines, a minus (-) for included source files, and is blank
otherwise.
The source line is converted to upper-case (except for strings and
comments), and will be truncated if necessary to make the entire
list line the proper width. The default width is 79. The width
can be modified with LINESIZE and PAGESIZE. The LINESIZE
directive can also be used to send special codes to your printer
(with the purpose of setting a font).
All the assembly directives mentioned in this description can be
looked up under Assembly Directives.
Symbol Table Listing 67
Symbol Table Listing
A symbol table listing can be activated with SYMDUMP+. The symbol
table is listed at the very end of the assembly. All symbols in
the program are included, except symbols within macro expansions
or declarations, and symbols that were defined in code that was
skipped due to conditional assembly.
The symbol table listing is divided five parts: Branch Locations,
Memory References, Equated Values, Defined Macros, and Undefined
Symbols. Each section starts a new page. The titles describing
the section replace the normal columnar headings.
The symbols are sorted alphabetically within each section. For
the purposes of alphabetization, underscores are ignored, for
example: the symbol A_B carries the same weight as AB, both of
these symbols would come after AA and before AC. If a value is
displayed with the symbol, it will be lined up to the right,
expressed in hex.
The branch locations section lists all the branch labels (types
NEAR and FAR) within the program, including the names of
procedures (which are just near labels). Each symbol is
accompanied by the location it represents.
The memory reference section lists all the memory reference labels
(type BYTE, WORD, etc.) within the program. Each symbol is
accompanied by the location it represents.
The equated values section lists all the symbols defined by the
EQU directive. Each symbol is accompanied by the value it
represents.
The defined macros section lists all the macros that where defined
within the program. Every macro that was defined will be listed,
whether or not it was used.
The undefined symbols section lists all symbols that were used but
not defined.
68 Assembly Messages
Assembly Messages
The integrity of the source code is constantly checked during
assembly. Lines containing errors will be flagged with an
appropriate error message. Some lines are only flagged with a
comment. A comment is more of an observation than an error.
Comments try to provide useful advice about the assembly.
Comments are not included in the error count displayed at the end
of assembly.
Error and comment messages will be sent to the list file if a
listing is being generated, otherwise the message will be
displayed to the screen followed by the source line that caused
the error or comment. A line may be flagged with more than one
message. Paging occurs indiscriminately, so that error or comment
messages may not appear on the same page as the line that they are
flagging.
Error messages start with "- - - Error: " and comment messages
start with "- - - Comment: ". Many error and comment messages are
followed on the same line by sections of the source code or
numbers. Numbers will either be decimal or hexadecimal (followed
by an "H"). If a line is flagged in an included file, the name of
the file will appear in parenthesis following the message. If a
line is flagged in a macro expansion, the last source line number
will appear in parenthesis. If both of these conditions are true,
then both the file name and line number will appear.
Many times the thing that caused one error will cause others, so
fixing up one error will often clear up others. If the reasons
for a particular error are unclear, try solving any previous
errors first.
Some errors may terminate the assembly. If this happens, the
message ">>>Cannot Continue<<<" will be displayed to the screen
and the speaker will be sounded.
Several assembly directives allow control over error flagging and
detection. The flagging of every undefined symbol occurrence can
be activated or deactivated with FLAGALL+ and FLAGALL-; the
detection of possible short unconditional jumps may be activated
or deactivated with JUMP+ and JUMP-; and the flagging of unused
symbols may be activated or deactivated with UNUSED+ and UNUSED-.
A programmer defined error may be created with ERROR. Finally,
the maximum number of errors detected before the assembly is
terminated can be controlled with ERRORMAX. See Assembly
Directives for more information on these directives.
The following is a description of all assembly messages:
Assembly Messages 69
Address error
There is some kind of error in an indirect memory operand.
Probably an illegal combination of addressing registers. The
legal addressing register combinations are: BX, BP, DI, SI,
BX+DI, BX+SI, BP+DI, and BP+SI. Any of these combinations may
also include an immediate data offset or displacement.
Ambiguous memory reference
A memory operand does not have its size properly specified.
Usually occurs when the operands are a memory operand and
immediate data and the size of the first is not defined. Under
those circumstances, the size of the memory operand should be
defined with an explicit BYTE or WORD function. This error also
occurs if a LABEL directive is missing its operand.
Cannot create list file: <file name>
The list file could not be created or opened. Probably because
of an invalid file name. The name of the list file is
displayed. Refer to the DOS manual for a description of legal
file names. Critical error.
Cannot create object file: <file name>
The object file could not be created or opened. Probably
because of an invalid file name. The name of the object file is
displayed. Refer to the DOS manual for a description of legal
file names. Critical error.
Could use JMPS: <displacement>
The branch location is close enough so that a short
unconditional jump (JMPS) instruction could be substituted for a
normal jump (JMP). The only effect this change would have is to
shorten the resulting object code by one byte, i.e. the code is
not incorrect the way it stands. The flagging of possible short
jumps is enabled with the JUMP+ directive.
Data too long in declaration: <operand value>
The initialization value (the second operand) of the DS
directive is more than eight bits. The value is displayed, it
should be in the range 0 to 255.
Disk full or write error: <file name>
An error occurred in writing to the object or list file.
Probably because the disk is full. The name of the file in
which the error occurred is displayed. Make sure that the disk
has enough free space, or send the object file or listing to
another disk or device. Critical error.
Division by zero
A division by zero occurred somewhere in an operand expression.
The The value of the divisor must be changed to something other
than zero.
70 Assembly Messages
Duplicate definition: <symbol>
A symbol was declared more than once. In addition to normal
symbol declarations at the start of source lines, the parameter
names after a MACRO directive are also considered symbol
declarations (though only local to that macro). Every duplicate
definition of a symbol is flagged. The symbol declarations must
be changed so that they are all unique. The symbol is
displayed.
ENDM without MACRO
An ENDM directive was found without a corresponding MACRO or
MACROC.
ENDP without PROC
An ENDP directive was found without a corresponding PROC.
EQU without symbol
The EQU directive was used without a symbol declaration. An
equate is meaningless without a symbol, thus a symbol
declaration is required.
IF statements nested too deeply: <maximum nest level>
Conditional IF or IFN directives were nested too deeply. The
maximum nest level is displayed.
Illegal addressing operand: <operand>
An operand within brackets is not a valid addressing operand.
The valid addressing operands are BX, BP, DI, SI, memory labels,
and immediate data. The operand is displayed.
Illegal argument for ANYSIZE: <argument>
The argument given for ANYSIZE is not valid. The argument
should be immediate data or a memory operand. The argument is
displayed.
Illegal argument for BYTE: <argument>
The argument given for BYTE is not valid. The argument should
be immediate data or a memory operand. The argument is
displayed.
Illegal argument for DWORD: <argument>
The argument given for DWORD is not valid. The argument should
be immediate data or a memory operand. The argument is
displayed.
Illegal argument for FAR:
The argument given for FAR is not valid. The argument should be
a near label, far label, or memory operand. The argument is
displayed.
Illegal argument for NEAR: <argument>
The argument given for NEAR is not valid. The argument should
be a near label, far label, memory operand, or immediate data.
The argument is displayed.
Assembly Messages 71
Illegal argument for NEG: <argument>
The argument given for NEG is not valid. The argument should be
immediate data. The argument is displayed.
Illegal argument for NOT: <argument>
The argument given for NOT is not valid. The argument should be
immediate data. The argument is displayed.
Illegal argument for OFFSET: <argument>
The argument given for OFFSET is not valid. The argument should
be a near label, far label, or memory label. The argument is
displayed.
Illegal argument for QWORD: <argument>
The argument given for QWORD is not valid. The argument should
be a memory operand. The argument is displayed.
Illegal argument for ST: <argument>
The argument given for ST is not valid. The argument should be
immediate data. ST, an 8087 stack operand, is not officially
implemented.
Illegal argument for TBYTE: <argument>
The argument given for TBYTE is not valid. The argument should
be a memory operand. The argument is displayed.
Illegal argument for WORD: <argument>
The argument given for WORD is not valid. The argument should
be immediate data or a memory operand. The argument is
displayed.
Illegal number or symbol: <operand field>: <illegal character>
An operand field started with a numerical digit (0 to 9), thus
is interpreted as a number, but has an illegal character in it.
Usually is a result of leaving the "H" off the end of
hexadecimal numbers. May also be the result of using a symbol
that was inadvertently declared with a digit as its first
character. The operand field and the illegal character within
it are displayed.
Illegal operand in declaration: <operand>
An operand in a DB or DW directive is invalid. All DB operands
must be immediate data or strings. All DW operands must be
immediate data. The operand is displayed.
72 Assembly Messages
Illegal operand(s): <first type> <second type>
One or both of the operands given for the instruction are
not valid. The first two operand types are displayed. The
valid operands for any given instruction may be looked up under
Instruction Set.
The following table shows the meaning of the displayed type
bits. Multiple bits may be active, like AX = 0006H (bits one
and two):
Bit Operand Type
--- ------------
0 no operand
1 non-segment register
2 accumulator (AX or AL)
3 segment register
4 memory operand in brackets
5 immediate data
6 string
7 near label
8 far label
9 memory label
10 (8087 stack)
11 (8087 stack top)
12 signed operand
13 undefined symbol
14 (internal use)
15 (internal use)
Illegal operator or symbol: <operator>
One of the special delimiters was out of place or some sort of
broader syntax error occurred in the operands of the
instruction. May be because of an illegal operand expression,
like AX+1. May be because of an extra operator, like 1+++1.
May be because of a generally illegal construct, like (1+) or
[OFFSET]. May be because of an illegal operator within a memory
operand, like [5*3] or [1-BX]. May be because of illegal
operators in the parameter names after the MACRO directive, like
A+B. The illegal character (operator) is displayed. The
operators AND, OR, XOR, and MOD will only show up as A, O, X,
and \.
Illegal printer code: <operand>
A printer code following the LINESIZE directive is not valid.
The printer codes must be 8 bit immediate data.
Illegal reference: <value>
The value of an equate changed during assembly and is thus not
valid. Probably because a changeable assembly constant was
used, or the equate referenced an operand with OFFSET in it
before the OFFSET argument was defined, or the equate referenced
another, not yet defined equate. The initial value of the
equate is displayed.
Assembly Messages 73
Illegal use of MACRO symbol: <symbol>
A macro symbol was used as an operand. Macros may only be used
as instructions. The symbol is displayed.
INCLUDE file not found: <file name>
The include file could not be found or opened. Probably because
of an incorrect file name. Make sure that all components of the
file name are correct. Remember that the source drive/path and
an extension of ASM are assumed if not otherwise specified. The
name of the include file is displayed.
INCLUDE's nested too deeply
An INCLUDE directive inside of an included file was encountered.
Include files may not be nested.
INCLUDE within macro
An INCLUDE directive inside of a macro expansion was detected.
INCLUDE's may not be placed in macros.
Invalid character in symbol: <symbol>
The symbol being declared contains invalid character(s).
Presently all symbols with a first character of "0" through "9"
(reserved for numbers) or a first character of "$" (reserved for
assembly constants) are flagged. Macro parameter names
(following a MACRO directive) can also be flagged in a similar
manner. The symbol must be changed so it conforms to the legal
format. The symbol is displayed. See Reserved Symbols.
Invalid operand size: <first size> <second size>
No version of the instruction was found with matching operand
sizes. This comment is provided to assist in fixing an Invalid
Operands error. The size of the first two operands are
displayed. The valid operands and sizes for any given
instruction may be looked up under Instruction Set.
The following table shows the meaning of the displayed size
bits. Multiple bits may be active, like 5 = 0003H (bits zero
and one):
Bit Operand Size
--- ------------
0 8 bits, byte
1 16 bits, word
2 32 bits, double word
3 64 bits, quadruple word
4 80 bits, ten byte
Bits 5 through 15 are for internal use.
LABEL without label
The LABEL directive was used without a symbol declaration. A
label declaration is meaningless without a symbol, thus a symbol
is required.
74 Assembly Messages
Line size out of range: <specified size>
The length of the line specified by a LINESIZE or PAGESIZE
directive is either too small or too large. The value must be
in the range 45 to 158. The value is displayed.
MACRO without symbol
The MACRO directive was used without a symbol declaration. A
macro declaration is meaningless without a symbol, thus a symbol
is required.
Macros nested too deeply: <maximum nest level>
Macros are being expanded too deeply. The maximum nest level is
displayed.
Missing ENDIF: <number>
At least one ENDIF directive was found to be missing when the
end of the source code was reached. The number of missing
ENDIF's are displayed.
Missing ENDM
An ENDM directive was found without a corresponding MACRO.
Missing ENDP: <number>
At least one ENDP directive was found to be missing when the end
of the program was reached. Since specific PROC's are not
matched to specific ENDP's, the actual error may exist anywhere
in the program, even though it isn't detected until the end of
the program. The number of missing ENDP's are displayed.
Missing IF
A NEXTIF, ELSEIF, ELSE, or ENDIF directive was found without a
corresponding IF or IFN. All conditional sections of source
code must start with an IF or IFN.
Missing or illegal operator: <field>
Two fields were found not separated by a comma or valid
operator. Individual components of an operand expression must
be separated by some kind of operator. The individual operands
of an instruction must be separated by commas. Something like a
misspelled AND operator could cause this error. The second of
the two fields are displayed.
Missing PROC
A RET instruction was found outside of a procedure. Since the
RET instruction needs a PROC directive to set the type of
return, all RET's must fall within a procedure. Near and far
returns can be encoded independent of procedure definitions with
RETN and RETF.
Missing right bracket
A memory operand using brackets came to an end without a right
bracket (via an end of line or comma). May occur because of a
general error in syntax, like [OFFSET], where the bracket is
passed to the OFFSET function as an argument and is overlooked.
Assembly Messages 75
Operand cannot be combined: <operand>
The operand may not be used in an expression. The operand is
displayed. Only immediate data may be used in expressions.
Operands are incompatible sizes: <first size> <second size>
The operands for the instruction are not compatible sizes,
though the instruction involves exchanging data between the two.
The sizes of the first two operands are displayed. See the
Invalid Operand Size error for a description of the size bits.
Out of memory for code table: <maximum lines>
The internal code table is full and no more lines can be
assembled. The maximum number of source lines that can be
assembled is displayed. See Memory Limitations. Critical
error.
Out of memory for macro table: <bytes available>
The internal macro storage area is full and no more macros can
be defined. The total available bytes of macro storage is
displayed. See Memory Limitations. Critical error.
Out of memory for symbol table: <symbol>: <bytes available>
The internal symbol table is full and no more symbols may be
defined. The symbol that caused the error and the total
available bytes for the symbol table is displayed. See Memory
Limitations. Critical error.
Overflow: <number>
A number or the result of an expression is too big or too small.
Individual numbers must be in the range 0 to 65535 (unsigned) or
+32767 to -32768 (signed). If any single value in an expression
is signed, the entire expression is considered signed. The
final result of an expression must fall in the same unsigned or
signed ranges as individual numbers. If the error occurs
because of an individual number, the number will be displayed.
Page size out of range: <specified size>
The length of the page specified by a PAGESIZE directive is
either too small or too large. The value must be in the range
15 to 255. The value is displayed.
Parenthesis nested too deeply
The parenthesis in an operand expression were nested too deeply.
Parenthesis may only be nested ten deep.
Parenthetical error
There was some kind of error in an operand expression involving
parenthesis, like ((1).
76 Assembly Messages
Phase error: <previous value>
The location counter somehow became out of phase with previous
assembly passes. The error may be occurring sometime previous
to its detection, since the phase is only checked for symbol
declarations (only labels). This error probably means that the
source code was assembled differently in different passes.
Could be caused by something like conditionally assembling a
section of the code based on the one of the time constants (like
$TIME1), which may be different each pass. Could also be caused
by directly manipulating the location counter in an unsound
fashion, like using assembly constants (which aren't really very
constant) to set the location counter. The previous location
counter value is displayed.
Procedures nested too deeply: <maximum nest level>
Procedure declarations are nested too deeply. The maximum nest
level is displayed.
Register size override: <first size> <second size>
The size of the register is not compatible with the size of the
memory operand. The size of the memory operand may explicitly
changed with a BYTE or WORD function. The sizes of the first
two operands are displayed. See the Invalid Operand Size error
for a description of the size bits. This message doesn't
necessarily indicate an error, but merely acts as a warning.
Should be byte data
The immediate data operand (port number) of an IN or OUT
instruction is not eight bits.
Source file not found: <file name>
The source file could not be found or opened. Probably because
of an incorrectly typed file name. Make sure that all
components of the file name are correct. Remember that the
default drive/path and an extension of ASM are assumed if not
otherwise specified. The name of the source file is displayed.
Critical error.
Source line too long: <excess>
The line within a macro expansion would be too long if all the
parameters in that line were inserted. The parameters or the
line itself must be shortened. The approximate amount by which
the line is too long by is displayed.
String not closed
A string field was started with a single quote but not closed by
a matching one. A matching single quote must be added.
Assembly Messages 77
Too far for short jump: <displacement>
The target of the branch is not close enough for a short jump
(its displacement should be in the range +127 to -128, or 007F
to FF80 hex). If the instruction is a JMPS, then JMP may be
used instead. If the instruction is one of the conditional
branches, the source code must be moved around so that target is
closer, or a combination of conditional and unconditional
branching must be used. The present displacement is displayed.
;you could change the following ...
Jz Toofar ;TOOFAR is too far for a short jump
;... to the following
Jnz Skipjump ;skip long jump on opposite condition
Jmp Toofar ;long jump to TOOFAR
Skipjump
Too many MACRO parameters: <maximum parameters>
Too many parameters are being passed to the macro upon
invocation. The maximum number of parameters is not determined
by the number specified in the macro declaration, but rather is
based on internal memory constraints. The number of parameters
must be reduced. The maximum allowed parameters are displayed.
Undefined assembly directive: <number>
Should not get this error. It means that the instruction is an
assembly directive that is not fully defined.
Undefined error
Should not get this error. It means that an undefined error
occurred.
Undefined symbol: <symbol>
The symbol was used but not defined anywhere. Might be because
the first digit of a hexadecimal number was not 0 through 9.
This error can be enabled for all subsequent occurrences of
the symbol with the FLAGALL+ directive.
Unrecognized instruction: <mnemonic>
The instruction mnemonic was not recognized. It is not an 8086
instruction, assembly directive, or a macro. The mnemonic is
displayed.
Unused symbol: <symbol>
The declared symbol was never used. This message does not
indicate an error, but rather assists in "cleaning up" the
source code. The detection of unused symbols enabled is enabled
with the UNUSED+ directive.
WASM detects checksum failure
The copy of WASM.COM is corrupted and cannot be used. If you
don't know why you're getting this message, try making a new
working copy from your master disk or the original archive file.
78 Assembly Messages
WASM detects incorrect DOS version
The operating system is pre-2.0. WASM requires PC or MS DOS 2.0
or greater to function.
WASM detects insufficient memory
There is not enough free memory for WASM to function. Though
your computer may have enough memory installed, device drivers
and memory resident programs could be using too much. See
Memory Limitations.
Instruction Set 79
Instruction Set
This is a brief list of all the legal predefined instructions and
their operand types. The instructions are divided up by function.
The groups are: assembly directives, data transfer, arithmetic,
logic, flag setting, control transfer, string manipulation, and
processor control. The assembly directives are more thoroughly
described under Assembly Directives. The 8086 instructions are
not thoroughly described in this documentation, you'll need
another source for that.
Instruction Format:
<mnemonic> = <short description>
<operand> [, <operand>, ...] [=<comment>]
Operand Types:
none no operands
reg register (non-segment)
seg segment register
accum AX or AL
mem memory operand
immed immediate data
near near label
string string data
symbol a unique symbol
Operands separated by slashes mean that either one may be used.
Operands in capital letters are the literal operands accepted.
Operands in brackets are optional, all others are required.
Numbers in parenthesis indicate the allowable size (number of
bits) for the specified operands. If no size is given then the
operands may be either 8 or 16 bit (where applicable).
******************************************************************
Assembly Directives
DB = declare bytes
immed/string [, immed/string, ...]
DS = declare storage
immed [, immed(8)] = bytes, value (default 0)
DW = declare words
immed [, immed, ...]
ELSE = conditional "else"
immed
ELSEIF = conditional "else-if"
immed
80 Instruction Set
ENDIF = end of conditional statement
none
ENDM = end of macro declaration
none
ENDP = end of procedure
none
EQU = equate, requires label
immed
ERROR = programmer defined error
string = error message
EXPAND+ = list macro expansions (default)
none
EXPAND- = do not list macro expansions
none
ERRORMAX = set maximum errors (default 65535)
immed
FLAGALL+ = flag all occurrences of undefined symbols
none
FLAGALL- = flag only first occurrence of undef. symbols (default)
none
IF = conditional "if"
immed
IFN = conditional "if not"
immed
INCLUDE = include source file
string = file name (default source drive and ext)
JUMP+ = flag long jumps that could be short
none
JUMP- = do not flag long jumps that could be short (default)
none
LABEL = define label, requires label
NEAR/FAR/BYTE/WORD/DWORD/QWORD/TBYTE/ANYSIZE
LINESIZE = set page width (default 79)
[immed] [, immed(8), ...] = page width, printer codes
LIST+ = generate listing (default if list file specified)
none
Instruction Set 81
LIST- = list output off
none
MACRO = start of macro declaration
[symbol, ...] = parameter names
MACROC = start of conditional macro declaration
[symbol, ...] = parameter names
NEXTIF = conditional "if", same level
immed
ORG = origin (default 100H)
immed = relative to location if signed
PAGE = start new page
[immed/string] = page number, subtitle
immed [, string] = page number, subtitle
PAGE+ = start auto paging
[immed/string] = page number, subtitle
immed [, string] = page number, subtitle
PAGE- = stop auto paging (default)
none
PAGESIZE = set page size (default 60,79)
immed [,immed] = page length, page width
PROC = beginning of procedure
NEAR/FAR
RESETC = reset byte counter
[immed] [,immed] = counter value, checksum value (default 0, 0)
SUBTITLE = set program subtitle
string = subtitle
SYMDUMP+ = symbol table dump on
none
SYMDUMP- = symbol table dump off (default)
none
TITLE = set program title
string [, string] = title, subtitle
UNUSED+ = flag unused symbols
none
UNUSED- = do not flag unused symbols (default)
none
82 Instruction Set
******************************************************************
Data Transfer
IN = input
accum, immed(8) = input from a fixed port
accum, DX = input from a variable port in DX
LAHF = load AH with flags
none
LDS = load DS and register (16)
reg, reg/mem
LEA = load effective address (16)
reg, reg/mem
LES = load ES and register (16)
reg, reg/mem
MOV = move
reg/mem, reg/seg
reg/seg, reg/mem
reg/mem, immed
OUT = output
immed(8), accum = output to fixed port
DX, accum = output to variable port in DX
POP = pop (16)
reg/seg/mem
POPF = pop flags
none
PUSH = push (16)
reg/seg/mem
PUSHF = pop flags
none
SAHF = store AH to flags
none
XCHG = exchange
reg/mem, reg
reg, reg/mem
XLAT = translate byte in AL
none
Instruction Set 83
******************************************************************
Arithmetic
AAA = ASCII adjust for add
none
AAD = ASCII adjust for divide
none
AAM = ASCII adjust for multiply
none
AAS = ASCII adjust for subtract
none
ADC = add with carry
reg/mem, reg
reg, reg/mem
reg/mem, immed
ADD = add
reg/mem, reg
reg, reg/mem
reg/mem, immed
CBW = convert byte to word
none
CWD = convert word to double word
none
DAA = decimal adjust for add
none
DAS = decimal adjust for subtract
none
DEC = decrement
reg/mem
DIV = divide, unsigned
[accum,] reg/mem = accum implicit
IDIV = integer divide, signed
[accum,] reg/mem = accum implicit
IMUL = integer multiply, signed
[accum,] reg/mem = accum implicit
INC = increment
reg/mem
84 Instruction Set
MUL = multiply, unsigned
[accum,] reg/mem = accum implicit
NEG = decrement
reg/mem
SBB = subtract with borrow
reg/mem, reg
reg, reg/mem
reg/mem, immed
SUB = subtract
reg/mem, reg
reg, reg/mem,
reg/mem, immed
******************************************************************
Logic
AND = and
reg/mem, reg
reg, reg/mem
reg/mem, immed
NOT = not
reg/mem
OR = or
reg/mem, reg
reg, reg/mem
reg/mem, immed
RCL = rotate through carry left
reg/mem = one time
reg/mem, CL = CL times
RCR = rotate through carry right
reg/mem = one time
reg/mem, CL = CL times
ROL = rotate left
reg/mem = one time
reg/mem, CL = CL times
ROR = rotate right
reg/mem = one time
reg/mem, CL = CL times
SAL = shift arithmetic left
reg/mem = one time
reg/mem, CL = CL times
Instruction Set 85
SAR = shift arithmetic right
reg/mem = one time
reg/mem, CL = CL times
SHL = shift logical left
reg/mem = one time
reg/mem, CL = CL times
SHR = shift logical right
reg/mem = one time
reg/mem, CL = CL times
XOR = xor
reg/mem, reg
reg, reg/mem
reg/mem, immed
******************************************************************
Flag Setting
CLC = clear carry
none
CLD = clear direction
none
CLI = clear interrupt
none
CMC = clear complement carry
none
CMP = compare
reg/mem, reg
reg, reg/mem
reg/mem, immed
STC = set carry
none
STD = set direction
none
STI = set interrupt
none
TEST = test
reg/mem, reg
reg, reg/mem
reg/mem, immed
86 Instruction Set
******************************************************************
Control Transfer
CALL = call
near = direct within segment
immed (offset), immed (segment) = direct intersegment
reg/mem = indirect within segment (16)
mem = indirect intersegment (32)
INT = interrupt
immed(8)
INT3 = type 3 interrupt
none
INTO = interrupt on overflow
none
IRET =interrupt return
none
JA = jump if above
near
JAE = jump if above or equal
near
JB = jump if below
near
JBE = jump if below or equal
near
JC = jump if carry
near
JCXZ = jump if CX equal to zero
near
JE = jump if equal
near
JG = jump if greater
near
JGE = jump if greater or equal
near
JL = jump if less
near
JLE = jump if less or equal
near
Instruction Set 87
JMP = unconditional jump
near = direct within segment
immed (offset), immed (segment) = direct intersegment
reg/mem = indirect within segment (16)
mem = indirect intersegment (32)
JMPS = unconditional short jump
near
JNA = jump if not above
near
JNAE = jump if not above or equal
near
JNB = jump if not below
near
JNBE = jump if not below or equal
near
JNC = jump if no carry
near
JNE = jump if not equal
near
JNG = jump if not greater
near
JNGE = jump if not greater or equal
near
JNL = jump if not less
near
JNLE = jump if not less or equal
near
JNO = jump if not overflow
near
JNP = jump if not parity
near
JNS = jump if not sign
near
JNZ = jump if not zero
near
JO = jump if overflow
near
88 Instruction Set
JP = jump if parity
near
JPE = jump if parity even
near
JPO = jump if parity odd
near
JS = jump if sign
near
JZ = jump if zero
near
LOOP = loop CX times
near
LOOPE = loop while equal
near
LOOPNE = loop while not equal
near
LOOPNZ = loop while not zero
near
LOOPZ = loop while zero
near
RET = return, type determined by procedure
none
immed = add immed to stack
RETF = within segment return
none
immed = add immed to stack
RETN = intersegment return
none
immed = add immed to stack
******************************************************************
String Manipulation
CMPSB = compare string byte
none
CMPSW = compare string word
none
LODSB = load string byte
none
Instruction Set 89
LODSW = load string word
none
MOVSB = move string byte
none
MOVSW = move string word
none
REP = repeat CX times
none
REPE = repeat while equal
none
REPNE = repeat while not equal
none
REPNZ = repeat while not zero
none
REPZ = repeat while zero
none
SCASB = scan string byte
none
SCASW = scan string word
none
STOSB = store string byte
none
STOSW = store string word
none
******************************************************************
Processor Control
HLT = halt
none
LOCK = bus lock prefix
none
NOP = no operation
none
SEG = segment override prefix
seg
90 Instruction Set
WAIT = wait
none
******************************************************************
External Subroutines 91
External Subroutines
Programs assembled by WASM may be used as external subroutines by
other programs. A programming language that can call pure binary
image, external, machine language subroutines should be able to
call programs assembled with WASM. BASIC and Turbo Pascal are two
languages that can do this. Refer to the BASIC or Pascal manual
for the specific implementation.
BASIC expects the external machine language subroutine to be in
the BLOAD format. This is easily done adding the proper header to
the file, which is as follows:
;this is a BLOAD header, it should
;be the first code in the program
Db 0fdh ;BLOAD marker
Dw 0f000H ;segment to load it at
Dw 0 ;offset to load it at
Dw $Size ;size of program
The segment and offset of the load can be any number, since it
should be specified by the programmer when loading it from BASIC.
Making load address F000:0000 (which is read only memory) will
prevent loading it over something important if the address is not
specified.
Turbo Pascal external subroutines do not require any special
format.
The code within Pascal subroutines must be relocatable. This
means that no references to the location counter should be made
(the location is undefined). Since memory labels cannot be used,
there is no good way to access declared local data; its probably
better to just do without such data. BASIC subroutines may or may
not have to be relocatable, depending upon where they are stored.
If the address is known beforehand (in an unused screen buffer for
instance), the code need not be relocatable and the starting
offset will be known and can be set with ORG. If the BASIC
subroutine is stored in a variable's data space or a file buffer,
then the code must be relocatable.
Machine language subroutines may be debugged by placing an INT3
instruction within the code and then running the entire program
(BASIC or Pascal) under DEBUG. When the subroutine is executed,
the INT3 will give control to the DEBUG program and allow you to
step through your code. Make sure to remove the INT3 and
reassemble the code when you are through debugging.
Programs that are assembled as subroutines are not directly
executable, thus it may be a wise idea to name them with an
extension other than .COM (which implies that a program is
executable).
92 Source Code Clarification
Source Code Clarification
Many of the conventions used by WASM are also used by other
assemblers and debuggers. This section compares WASM to other
assemblers and the DEBUG program provided with DOS. This section
also points out a few particulars of WASM syntax.
Some assemblers add a suffix to the mnemonic to indicate the size
of the operation, whether immediate data is involved, and the type
of calls, jumps, and returns that are being used. WASM identifies
the type and size of the instruction mainly on the basis of the
operands, in accordance with the DOS DEBUG program.
WASM allows the programmer to define the size of the operand
through the use of a functional operand (BYTE, WORD, etc.). This
is very similar to the structure used by the DEBUG program and the
IBM Macro Assembler.
;the following statement in WASM...
Mov WOrD [5+sI+ 10 +Bp+5], not 1111111111111111B
; ...is disassembled as the following in DEBUG
; MOV W,[BP+SI+14],0000 ;DOS 1.1 DEBUG
; MOV WORD PTR [BP+SI+14],0000 ;DOS 2.0 DEBUG
Near and far indirect branching may be implemented by specifying
the size of the operand or actually using the NEAR and FAR
functions. Debug uses FAR for far branching and nothing for near
branching.
Call Near [Bx] ;
Call Word [Bx] ;these two are the same thing to WASM
;Call [Bx] ;debug format
Call Far [Bx] ;
Call Dword [Bx] ;these two are the same thing to WASM
;Call Far [Bx] ;debug format
The size of the string manipulation instructions are specified by
a B or W suffix added to the mnemonic. This is the same as the
DEBUG program.
Movsb ;move string byte
Movsw ;move string word
JMPS is the mnemonic that WASM uses to specify a short
unconditional jump to a near label. JMP always means a long jump.
The (DOS 2.0) DEBUG program uses JMP for both long and short
jumps.
Jmps Location1 ;short unconditional jump
Jmp Location1 ;long unconditional jump
Source Code Clarification 93
WASM sets the type of return for a RET based on the procedure
type. A near (within segment) or far (intersegment) return may be
encoded without using a PROC through the use of RETN and RETF
respectively. The DEBUG program uses RET to indicate a near
return and a RETF to indicate a far return.
Proc Far ;<---
Ret ;far return ; far routine
Retn ;near return ;
Retf ;far return ;
;
Proc Near ; <---
Ret ;near return ; ; near routine
Retn ;near return ; ;
Retf ;far return ; ;
Endp ; <---
;
Ret ;far return ;
Endp ;<---
The bit shifting instructions (SHL, SHR, ROL, etc.) are
interpreted to be a single shift by WASM if there is only one
operand (the operand to be shifted). Shifts using the CL register
as a counter are implemented by specifying CL as the second
operand. The DEBUG program requires a "1" as a second operand to
specify a single shift.
Rol Ax ;roll AX left by one
; Rol Ax,1 ;roll AX left by one, DEBUG format
Shr Byte [Bx],Cl ;shift 8 bits at [BX] CL times
Some assemblers leave out an operand if the operand is implicit in
the instruction. AX is implicit in the following instructions:
IN, OUT, MUL, IMUL, DIV, and IDIV. WASM requires the AX (or AL)
register in the IN and OUT instructions but allows the others with
or without it. The DEBUG program leaves out the AX or AL register
on multiply or divide instructions, but does not on the others.
In Ax,Dx ;AX receives input word from port in DX
;both of the following are: AX = DX.AX x CX
Mul Ax,Cx ;WASM allows this
Mul Cx ;WASM and DEBUG allow this
WASM and DEBUG implement instruction prefixes as a separate
instruction, i.e. they appear on the line above the instruction to
modify. The prefixes are: LOCK, REP, REPE, REPNE, REPNZ, REPZ,
and SEG.
Rep
Stosb ;store byte CX times
Seg Ss
Mov Ax,[Bx] ;[Bx] is in the stack segment
94 Source Code Clarification
WASM and DEBUG both specify indirect memory operands by putting
all values and registers inside the brackets.
;this in WASM ...
Sub [Bx+10],Ax
Sub [BX+Data],Ax
;... may be implemented by others like one of these
; Sub [Bx]+10,Ax
; Sub 10[Bx],Ax
; Sub Data[Bx],Ax
Data Label Word
The mnemonic for an optimized type 3 interrupt is INT3.
;both of statements these cause type 3 interrupts,
;but the first uses only one byte of code
Int3
Int 3
WASM assumes the entire program and all data are in the same
segment, so there are no segment definitions. The location
counter is automatically started at 100H, in accordance with COM
file format. Though WASM doesn't allow segment definitions, a
program may, of course, set up and maintain its own segments
during execution.
The implementation and usage of assembly directives vary widely
among assemblers. The general format of procedure, macro, and
data declarations are similar, but mostly incompatible among
assemblers. WASM uses a fairly simplified set of directives, most
of which are comparable, though not compatible, to other
assemblers.
Several 8086 instructions mean the same thing as other
instructions and produce identical object code. The DEBUG program
always disassembles these instructions using one particular
mnemonic. One example is JNLE (jump not less or equal) and JG
(jump greater). The DEBUG program disassembles both of these
instructions as JG.
Symbols that are declared within skipped source code should be
undefined. These symbols, though, are placed in the symbol table
anyway and still subject to duplicate definition and other symbol
declaration errors. This will hopefully be corrected in future
versions of WASM.
Source Code Clarification 95
;in theory the second two symbols don't really
;exist, since they are in source code that is
;skipped because of the false IF directive; in
;spite of "not existing," the second declaration
;of SYMBOL2 causes a duplicate definition
Symbol2
If 0
Symbol1 ;considered undefined
Symbol2 ;duplicate definition
Endif
There is an uncaught error for certain registers as operands.
When the operand DX is used in IN's and OUT's, and CL is used for
shifts and rolls, WASM only looks for a register type, not those
particular registers. This means that in those cases any register
will work in place of a DX or CL (except a segment register).
Also WASM does not search for extra operands, they do not cause
errors if they exist.
;some uncaught errors
In Ax,Bx
Shl Ax,Bx
Mov Ax,Bx,Cx,Dx
96 Memory Limitations
Memory Limitations
WASM requires a about 100 kilobytes (K) of free RAM for execution.
The only aspect of WASM that varies with the amount of available
memory is the macro storage capacity. With a minimum amount of
memory (100K), less than a 1000 bytes of macro storage is
available. Every free byte after that, up to 64K, is used for
macro storage. With 164K bytes available, the maximum usable
amount of memory, about 1600 lines at 40 characters apiece can be
stored. The length of the macro lines is significant, i.e. the
shorter the lines, the more lines that can be stored.
The symbol table has room for about 2000 symbols at 10 bytes
apiece. Like macro lines, the shorter the symbols, the more
symbols that can be stored. An internal code table (which saves a
partial tokenized assembly of the program) has room for 10800
entries. Every source line creates an entry in the code table,
except blank lines and lines resulting from a macro expansion.
Lines that are skipped due to conditional assembly and the
conditional directives themselves DO take up room in the code
table, even though they do not show up in the assembly. The
symbol table size and code table size do not change, even if the
memory is available.
Bibliography 97
Bibliography
These books were used as references in the development of WASM
and the writing of this documentation. In addition to this list,
there are many other excellent sources of information on the 8086
microprocessor and assembly language programming.
"BASIC Version 1.10." 2st ed. Boca Raton, FL: International
Business Machines Corp., 1981 and 1982.
Duncan, Ray. "Advanced MS DOS." Redmond, WA: Microsoft Press,
1986.
"iAPX 86/88, 186/188 User's Manual." Santa Clara, CA: Intel
Corp., 1985.
King, Richard A. "The IBM PC-DOS Handbook." Berkeley, CA: SYBEX
Inc., 1983.
Morgan, Christopher L., and Mitchell Waite. "8086/8088 16-Bit
Microprocessor Primer." Peterborough, NH: BYTE/McGraw-Hill,
1982.
"Technical Reference." Rev. ed. Boca Raton, FL: International
Business Machines Corp., 1981, 1982, 1983, and 1984.
"Turbo Pascal Reference Manual Version 3.0." Scotts Valley, CA:
Borland International Inc., 1983, 1984, and 1985.
98 Index
Index
' 11 DEBUG program 92
() 14 Declaring data, 35
, 6 byte 35
; 7 examples 35
? 11 location 35
[] 11 storage 35
$ 61 string 35
$CHKSUM constant 61 word 35
$COUNT constant 61 Default file name 4
$DATE1 constant 62 Delimiter 6
$DATE2 constant 62 Directive, 6, 37
$LOC constant 62 compatibility 94
$SIZE constant 62 conditional 19
$SUM constant 62 list of 79
$TIME1 constant 63 syntax 9
$TIME2 constant 63 Distribution policy 3
$VERSION constant 63 Dollar sign 61
Addressing, DS directive 35, 38
direct 11 DW directive 35, 38
indirect 11 DWORD function 56, 92
registers 11 EDLIN program 6
ANYSIZE function 55 ELSE directive 20, 21, 22, 38
ASM filename extension 4 ELSEIF directive 20, 21, 22
Assembling programs 4 39
BASIC subroutines 91 End of file 6
Basic syntax 6 ENDIF directive 21, 22, 39
Blank line 7 ENDM directive 28, 40
Bload, ENDP directive 17, 40
address 91 EQU directive 40
format 91 Equates 8
Brackets 11 Error, 5, 68
Bug, in WASM 94, 95 AND 14
BYTE function 55, 92 count 68
CALL instruction 17 critical 68
COM filename extension 4 description of messages 68
Comma 6 flagging 68
Comment, message 68
description of messages 68 MOD 14
message 68 multiple 68
source 7 OR 14
Compatibility of source XOR 14
code 92 Error code,
CON device 4 upon termination 5
Conditional assembly, 18 ERROR directive 41, 68
directives 19 ERRORLEVEL batch command 5
expansion of macros 30 ERRORMAX directive 42, 68
in macros 28 EXPAND+ directive 34, 42, 65
nested 22 EXPAND- directive 34, 42, 65
Constant 61 Expression, 14
Control characters 6 examples 14
Data declaration 35 operators 14
DB directive 35, 37 signed 14
Index 99
FAR function 56, 92 Macro (cont.),
Field, 6 invocation 30
interpretation 6 listing 34
File name, default 4 local symbols 28
FLAGALL+ directive 43, 68 memory limitation 96
FLAGALL- directive 43, 68 nest level 34
IF directive 19, 21, 22, 43 nested 32
IFN directive 19, 43 nul parameter 28, 30
Immediate data, 10 parameter 28
characters 10 parameter passing 30
in expressions 14 parameter substitution 30
size 11 parameter testing 28
INCLUDE directive 44 parameter validity 28
Instruction, 6, 9, 37 recursive 32
bit shifting 93 recursive parameter 32
disassembly 94 source lines 28
list of 79 symbol declaration 28
prefix and override 93 MACRO directive 28, 47
string 92 MACROC directive 33, 47
syntax 6 Memory,
Interrupt, type 3 91 code table 96
JMP instruction 92 label 8
JUMP+ directive 44, 68 limitation 96
JUMP- directive 44, 68 minimum 96
Label, 8 segments 94
in expressions 14 symbol table 96
memory 8, 35 Memory operand, 11
near 8 addressing registers 11
LABEL directive 35, 45 direct addressing 11
Line, indirect addressing 11
blank 7 size 12
syntax 6 Message,
LINESIZE directive 46 descriptions 68
List, 4, 65 during assembly 68
columnar headings 66 NEAR function 56, 92
header 65 NEG function 57
line 66 NEXTIF directive 19, 21, 22
page number 65 48
paging 65 NOT function 57
subtitle 65 Number, 10
symbol table 67 binary 10
title 65 decimal 10
List file 4 hexadecimal 10
LIST+ directive 46, 65 signed 10
LIST- directive 46, 65, 65 size 11
LST filename extension 4 Object file 4
Macro, 8, 27 OFFSET function 58
conditional 33 Operand, 6, 10
conditional assembly 28 compatibility 25
declaration 28 conditional testing 25
errors in 34 constants 61
expansion 30 examples 12
field interpretation 28 expressions 14
global symbols 28 false 24
100 Index
Operand (cont.), Source file (cont.),
functional 55 external 44
implicit 93 type 6
required 10 Spaces 6
size 11 Statistics, assembly 5
syntax 6 String, 11
true 24 declaration 35
type 10, 25 Structured programing 16
Operator, 14 Subroutine, 91
conditional 24 BASIC 91
ORG directive 49 debugging 91
Origin, 49 location counter 91
default 94 naming 91
PAGE directive 49, 65 Pascal 91
Page number 65 relocation 91
PAGE+ directive 50, 65 SUBTITLE directive 52, 65
PAGE- directive 50, 65 Symbol, 6, 8
PAGESIZE directive 50, 65 as instructions 8
Parameter, as operands 8
command line 4 declaration 8
command line examples 5 declaration syntax 6
macro 27, 28 label 8
procedural 17 location of declaration 8
Parenthesis, 14 required declaration 6
signed 14 reserved 64
Pascal subroutines 91 table 8
Printer 4 type 8
PRN device 4 type determination 8
PROC directive 17, 51 undefined 94
Procedure, 17 uniqueness 8, 64, 94
declaration 17 Symbol table, 8
far 17 list 67
local data 17 memory limitation 96
near 17 SYMDUMP+ directive 52, 65, 67
nested 17 SYMDUMP- directive 52
Program structure 16 System requirements 1
Question mark 11 TBYTE function 59
Quotation mark 11 Termination of assembly 68
QWORD function 58 TITLE directive 53, 65
Register, 10 TYPE function 25, 59
16 bit 11 UNUSED+ directive 53, 68
8 bit 10 UNUSED- directive 53, 68
segment 11 VALUE function 25, 59
size 12 WORD function 59, 92
Registration 3
RESETC directive 51
RET instruction 17, 93
Semi-colon 7
SIZE function 25, 58
Source code,
clarification 92
compatibility 92
external 44
Source file, 4